根据属性取消透视xml文档
时间:2020-03-05 18:59:50 来源:igfitidea点击:
我有一个简单的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="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>
回答
<xsl:template match="row"> <row A="{$A}" X="{$X}" /> <row A="{$A}" Y="{$Y}" /> <row A="{$A}" Z="{$Z}" /> </xsl:template>
加上明显的样板。
回答
这更复杂,但也更通用:
<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: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>,因为那一切都是XSLT指令。
如果我们使用的是XSLT 2.0,那么可以使用一些语法上的技巧,例如XPath中的except
运算符以及直接在<xsl:attribute>上使用select属性的功能:
<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>