我有xml,其中包含一些文档:
<document>
<line id="0">
<field id="0"><![CDATA[H:doc1]]></field>
</line>
<line id="1">
<field id="0"><![CDATA[L:1]]></field>
</line>
<line id="2">
<field id="0"><![CDATA[L:2]]></field>
</line>
<line id="3">
<field id="0"><![CDATA[L:3]]></field>
</line>
<line id="4">
<field id="0"><![CDATA[H:doc2]]></field>
</line>
<line id="5">
<field id="0"><![CDATA[L:1]]></field>
</line>
</document>
H =文档标题,L =行项目。在这个例子中,有两个H表示两个文件,它们编号为doc1和doc2。 doc1有三个订单项,doc2有一个订单项。
如何使用xslt版本1转换数据以获得此结果:
<documents>
<document>
<header>
<number>doc1</number>
</header>
<line-item>
<line-number>1</line-number>
<line-number>2</line-number>
<line-number>3</line-number>
</line-item>
</document>
<document>
<header>
<number>doc2</number>
</header>
<line-item>
<line-number>1</line-number>
</line-item>
</document>
</documents>
答案 0 :(得分:5)
此XSLT 1.0转换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kFollowing"
match="line[starts-with(field,'L:')]"
use="generate-id(preceding-sibling::line
[starts-with(field,'H:')]
[1]
)"/>
<xsl:template match="/">
<documents>
<xsl:apply-templates/>
</documents>
</xsl:template>
<xsl:template match="line[starts-with(field,'H:')]">
<document>
<header>
<number><xsl:value-of select="substring-after(field,'H:')"/></number>
<line-item>
<xsl:apply-templates mode="inGroup" select=
"key('kFollowing', generate-id())"/>
</line-item>
</header>
</document>
</xsl:template>
<xsl:template match="line" mode="inGroup">
<line-number>
<xsl:value-of select="substring-after(field,'L:')"/>
</line-number>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
应用于提供的XML文档:
<document>
<line id="0">
<field id="0"><![CDATA[H:doc1]]></field>
</line>
<line id="1">
<field id="0"><![CDATA[L:1]]></field>
</line>
<line id="2">
<field id="0"><![CDATA[L:2]]></field>
</line>
<line id="3">
<field id="0"><![CDATA[L:3]]></field>
</line>
<line id="4">
<field id="0"><![CDATA[H:doc2]]></field>
</line>
<line id="5">
<field id="0"><![CDATA[L:1]]></field>
</line>
</document>
生成想要的正确结果:
<documents>
<document>
<header>
<number>doc1</number>
<line-item>
<line-number>1</line-number>
<line-number>2</line-number>
<line-number>3</line-number>
</line-item>
</header>
</document>
<document>
<header>
<number>doc2</number>
<line-item>
<line-number>1</line-number>
</line-item>
</header>
</document>
</documents>
解释:使用键方便地指定并选择“标题”后面的完整的相邻“行”组。
答案 1 :(得分:3)
这里也是一个XSLT 2.0解决方案,使用<xsl:for-each-group starting-with="...">
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<documents>
<xsl:for-each-group select="*"
group-starting-with="line[starts-with(field,'H:')]">
<document>
<header>
<number><xsl:value-of select="substring-after(field,'H:')"/></number>
<line-item>
<xsl:apply-templates select="current-group()[position() >1]"/>
</line-item>
</header>
</document>
</xsl:for-each-group>
</documents>
</xsl:template>
<xsl:template match="line">
<line-number>
<xsl:value-of select="substring-after(field,'L:')"/>
</line-number>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<document>
<line id="0">
<field id="0"><![CDATA[H:doc1]]></field>
</line>
<line id="1">
<field id="0"><![CDATA[L:1]]></field>
</line>
<line id="2">
<field id="0"><![CDATA[L:2]]></field>
</line>
<line id="3">
<field id="0"><![CDATA[L:3]]></field>
</line>
<line id="4">
<field id="0"><![CDATA[H:doc2]]></field>
</line>
<line id="5">
<field id="0"><![CDATA[L:1]]></field>
</line>
</document>
产生了想要的正确结果:
<documents>
<document>
<header>
<number>doc1</number>
<line-item>
<line-number>1</line-number>
<line-number>2</line-number>
<line-number>3</line-number>
</line-item>
</header>
</document>
<document>
<header>
<number>doc2</number>
<line-item>
<line-number>1</line-number>
</line-item>
</header>
</document>
</documents>
解释:<xsl:for-each-group>
,其group-starting-with
属性,current-group()
函数。