题
我有一个简单的xml文件,看起来像下列段。我需要写一XSLT改变,基本上是'unpivots'这一文件基于一些属性。
<?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指令。
如果你使用XSLT2.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