문제

XML 문서가 있으며 속성 중 하나의 값을 변경하고 싶습니다.

먼저 입력에서 출력까지 모든 것을 복사했습니다.

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

그리고 이제 속성의 값을 변경하고 싶습니다. "type" 이름이 지정된 모든 요소에서 "property".

도움이 되었습니까?

해결책

간단한 예에서 테스트 한 경우 잘 작동합니다.

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="@type[parent::property]">
  <xsl:attribute name="type">
    <xsl:value-of select="'your value here'"/>
  </xsl:attribute>
</xsl:template>

Tomalak의 제안을 포함하도록 편집되었습니다.

다른 팁

이 문제에는 고전적인 솔루션이 있습니다: 사용 및 재정의 그만큼 ID 템플릿 가장 기본적이고 강력한 XSLT 디자인 패턴 중 하나입니다.:

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:param name="pNewType" select="'myNewType'"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="property/@type">
        <xsl:attribute name="type">
            <xsl:value-of select="$pNewType"/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

이 XML 문서에 적용될 때:

<t>
  <property>value1</property>
  <property type="old">value2</property>
</t>

원하는 결과가 생성됩니다:

<t>
  <property>value1</property>
  <property type="myNewType">value2</property>
</t>

루트 요소에 XMLNS 정의가 있으면 상위 두 가지 답변이 작동하지 않습니다.

<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml">
    <property type="old"/>
</html>

모든 솔루션은 위의 XML에서 작동하지 않습니다.

가능한 솔루션은 다음과 같습니다.

<?xml version="1.0"?> 

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:template match="node()[local-name()='property']/@*[local-name()='type']">
      <xsl:attribute name="{name()}" namespace="{namespace-uri()}">
                some new value here
          </xsl:attribute>
  </xsl:template>

  <xsl:template match="@*|node()|comment()|processing-instruction()|text()">
      <xsl:copy>
          <xsl:apply-templates select="@*|node()|comment()|processing-instruction()|text()"/>
      </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

대상 속성과 일치하는 템플릿이 필요하며 다른 것은 없습니다.

<xsl:template match='XPath/@myAttr'>
  <xsl:attribute name='myAttr'>This is the value</xsl:attribute>
</xsl:template>

이것은 이미 가지고있는 "모든 것"에 추가됩니다 (실제로 XSLT에서 항상 기본적으로 존재합니다). 보다 구체적인 일치를 갖는 것은 선호도에 사용됩니다.

간단한 노드에서 하나의 속성을 삭제하고 싶었던 비슷한 경우가 있었으며 속성 이름을 읽을 수있는 축을 알 수 없었습니다. 결국, 내가해야 할 일은 사용하는 것뿐입니다.

@*[name(.)!='AttributeNameToDelete']

다음 XML의 경우 :

<?xml version="1.0" encoding="utf-8"?>
<root>
    <property type="foo"/>
    <node id="1"/>
    <property type="bar">
        <sub-property/>
    </property>
</root>

다음 xslt와 함께 일할 수있었습니다.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="//property">
        <xsl:copy>
            <xsl:attribute name="type">
                <xsl:value-of select="@type"/>
                <xsl:text>-added</xsl:text>
            </xsl:attribute>
            <xsl:copy-of select="child::*"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

소스 XML 문서가 고유 한 네임 스페이스가있는 경우 스타일 시트에 네임 스페이스를 선언하고 접두사를 할당하고 소스 XML의 요소를 참조 할 때 해당 접두사를 사용해야합니다.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml">

<xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes" />

<!-- identity transform -->
<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>

<!-- exception-->    
<xsl:template match="xhtml:property/@type">
    <xsl:attribute name="type">
        <xsl:text>some new value</xsl:text> 
    </xsl:attribute>
</xsl:template>

</xsl:stylesheet>

또는 원하는 경우 :

...
<!-- exception-->    
<xsl:template match="@type[parent::xhtml:property]">
  <xsl:attribute name="type">
        <xsl:text>some new value</xsl:text> 
  </xsl:attribute>
</xsl:template>
...

부록 : XML 네임 스페이스가 미리 알려지지 않은 경우가 거의없는 경우에는 다음을 수행 할 수 있습니다.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes" />

<!-- identity transform -->
<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>

<!-- exception -->
<xsl:template match="*[local-name()='property']/@type">
    <xsl:attribute name="type">
        <xsl:text>some new value</xsl:text> 
    </xsl:attribute>
</xsl:template>

물론, 소스 XML 문서에 "property"라는 요소가 포함되어 있다는 것을 미리 알 수있는 시나리오를 상상하기가 매우 어렵습니다. "type"이라는 속성이있는 속성이 있지만 문서의 네임 스페이스를 알지 못합니다. 나는 주로 자신의 솔루션을 간소화 할 수있는 방법을 보여주기 위해 이것을 추가했습니다.

나는 또한 같은 문제를 발견했고 다음과 같이 해결했습니다.

<!-- identity transform -->
<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

<!-- copy property element while only changing its type attribute -->
<xsl:template match="property">
  <xsl:copy>
    <xsl:attribute name="type">
      <xsl:value-of select="'your value here'"/>
    </xsl:attribute>
    <xsl:apply-templates select="@*[not(local-name()='type')]|node()"/>
  <xsl:copy>
</xsl:template>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top