문제
다음 코드 조각과 같은 간단한 XML 문서가 있습니다.기본적으로 일부 속성을 기반으로 이 문서를 '피벗 해제'하는 XSLT 변환을 작성해야 합니다.
<?xml version="1.0" encoding="utf-8" ?>
<root xmlns:z="foo">
<z:row A="1" X="2" Y="n1" Z="500"/>
<z:row A="2" X="5" Y="n2" Z="1500"/>
</root>
이것이 내가 기대하는 결과입니다.
<?xml version="1.0" encoding="utf-8" ?>
<root xmlns:z="foo">
<z:row A="1" X="2" />
<z:row A="1" Y="n1" />
<z:row A="1" Z="500"/>
<z:row A="2" X="5" />
<z:row A="2" Y="n2"/>
<z:row A="2" Z="1500"/>
</root>
당신의 도움을 주셔서 감사합니다.
해결책
<xsl:template match="row">
<row A="{$A}" X="{$X}" />
<row A="{$A}" Y="{$Y}" />
<row A="{$A}" Z="{$Z}" />
</xsl:template>
게다가 명백한 상용구.
다른 팁
필요한 전체 스타일시트는 다음과 같습니다(네임스페이스가 중요하므로).
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:z="foo">
<xsl:template match="root">
<root>
<xsl:apply-templates />
</root>
</xsl:template>
<xsl:template match="z:row">
<xsl:variable name="A" select="@A" />
<xsl:for-each select="@*[local-name() != 'A']">
<z:row A="{$A}">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="." />
</xsl:attribute>
</z:row>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
나는 리터럴 결과 요소를 사용하는 것을 훨씬 선호합니다(예: <z:row>
)보다는 <xsl:element>
및 속성 값 템플릿( {}
속성 값의 s)가 아닌 <xsl:attribute>
가능한 경우 코드가 더 짧아지고 생성 중인 결과 문서의 구조를 더 쉽게 볼 수 있습니다.다른 사람들이 선호하는 <xsl:element>
그리고 <xsl:attribute>
왜냐하면 모든 것이 XSLT 명령어이기 때문입니다.
XSLT 2.0을 사용하는 경우 도움이 되는 몇 가지 구문상의 세부 사항이 있습니다. except
XPath의 연산자와 select
직접적으로 속성을 부여하다 <xsl:attribute>
:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
xmlns:z="foo">
<xsl:template match="root">
<root>
<xsl:apply-templates />
</root>
</xsl:template>
<xsl:template match="z:row">
<xsl:variable name="A" as="xs:string" select="@A" />
<xsl:for-each select="@* except @A">
<z:row A="{$A}">
<xsl:attribute name="{local-name()}" select="." />
</z:row>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
이는 더 복잡하지만 더 일반적입니다.
<xsl:template match="z:row">
<xsl:variable name="attr" select="@A"/>
<xsl:for-each select="@*[(local-name() != 'A')]">
<xsl:element name="z:row">
<xsl:copy-of select="$attr"/>
<xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:template>
다음은 약간의 무차별적인 방법입니다.
<xsl:template match="z:row">
<xsl:element name="z:row">
<xsl:attribute name="A">
<xsl:value-of select="@A"/>
</xsl:attribute>
<xsl:attribute name="X">
<xsl:value-of select="@X"/>
</xsl:attribute>
</xsl:element>
<xsl:element name="z:row">
<xsl:attribute name="A">
<xsl:value-of select="@A"/>
</xsl:attribute>
<xsl:attribute name="Y">
<xsl:value-of select="@Y"/>
</xsl:attribute>
</xsl:element>
<xsl:element name="z:row">
<xsl:attribute name="A">
<xsl:value-of select="@A"/>
</xsl:attribute>
<xsl:attribute name="Z">
<xsl:value-of select="@Z"/>
</xsl:attribute>
</xsl:element>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
제휴하지 않습니다 StackOverflow