Unpivot基于属性的xml doc

时间:2008-09-17 19:49:28

标签: xml xslt unpivot

我有一个简单的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>

感谢您的帮助。

4 个答案:

答案 0 :(得分:3)

这是您需要的完整样式表(因为命名空间很重要):

<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>和属性值模板(属性值中的那些{})而不是<xsl:attribute>尽可能使用<xsl:element>因为它使代码更短,并使您更容易看到您正在生成的结果文档的结构。其他人更喜欢<xsl:attribute>except,因为那时所有内容都是XSLT指令。

如果您正在使用XSLT 2.0,那么有一些语法细节可以提供帮助,即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> 属性的功能:

{{1}}

答案 1 :(得分:1)

<xsl:template match="row">
    <row A="{$A}" X="{$X}" />
    <row A="{$A}" Y="{$Y}" />
    <row A="{$A}" Z="{$Z}" />
</xsl:template>

另外还有明显的样板。

答案 2 :(得分:1)

这更复杂但也更通用:

<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>

答案 3 :(得分:0)

这是一种蛮力的方式:

    

<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>