Xml XSLT将项目移动到同一级别的其他标记中
xslt有一个问题: 这是输入文件:Xml XSLT将项目移动到同一级别的其他标记中,xml,xslt,xpath,Xml,Xslt,Xpath,xslt有一个问题: 这是输入文件: <root> <header/> <item/> … other n-1 <item/> <header/> <item/> … other m-1 <item/> </root> …其他n-1 …其他m-1 因此,标题和项位于同一级别(/root)。 必须将其转换为以下格式: <root2> &l
<root>
<header/>
<item/>
… other n-1 <item/>
<header/>
<item/>
… other m-1 <item/>
</root>
…其他n-1
…其他m-1
因此,标题和项位于同一级别(/root)。
必须将其转换为以下格式:
<root2>
<header2>
<item2/>
…<item2/> // the first n-items up
</header2>
<header2>
<item2/>
…<item2/> // the last m-items up
</header2>
</root2>
…//第一个n项向上
…//上一个m项
因此,基本上,第一个n项必须在第一个标题中移动,而第二组项必须在第二个标题中移动。知道怎么得到这个吗
谢谢
随机化样本XML:
<root>
<header/>
<item>1</item>
<item>2</item>
<item>3</item>
<header/>
<item>5</item>
<item>6</item>
<item>7</item>
</root>
1.
2.
3.
5.
6.
7.
使用分组的XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="k" match="item" use="count(preceding-sibling::header)"/>
<xsl:template match="/">
<root2>
<xsl:apply-templates select="root/item[generate-id(.) = generate-id(key('k', count(preceding-sibling::header)))]" mode="a"/>
</root2>
</xsl:template>
<xsl:template match="item" mode="a">
<header2>
<xsl:apply-templates select="key('k', count(preceding-sibling::header))"/>
</header2>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
或简单的特定XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<root2>
<header2>
<xsl:apply-templates select="root/item[count(preceding-sibling::header) = 1]"/>
</header2>
<header2>
<xsl:apply-templates select="root/item[count(preceding-sibling::header) = 2]"/>
</header2>
</root2>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
两者产生相同的输出:
<root2>
<header2>
<item>1</item>
<item>2</item>
<item>3</item>
</header2>
<header2>
<item>5</item>
<item>6</item>
<item>7</item>
</header2>
</root2>
1.
2.
3.
5.
6.
7.
这是一个更简单、更有效的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:key name="kFollowing" match="item"
use="generate-id(preceding-sibling::header[1])"/>
<xsl:template match="/*">
<root>
<xsl:apply-templates select="header"/>
</root>
</xsl:template>
<xsl:template match="header">
<heather2>
<xsl:copy-of select="key('kFollowing', generate-id())"/>
</heather2>
</xsl:template>
</xsl:stylesheet>
<root>
<header/>
<item>1</item>
<item>2</item>
<item>3</item>
<header/>
<item>5</item>
<item>6</item>
<item>7</item>
</root>
<root>
<heather2>
<item>1</item>
<item>2</item>
<item>3</item>
</heather2>
<heather2>
<item>5</item>
<item>6</item>
<item>7</item>
</heather2>
</root>
<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="/*">
<root>
<xsl:for-each-group select="item"
group-adjacent=
"generate-id(preceding-sibling::header[1])">
<header2>
<xsl:sequence select="current-group()"/>
</header2>
</xsl:for-each-group>
</root>
</xsl:template>
</xsl:stylesheet>
<root>
<header2>
<item>1</item>
<item>2</item>
<item>3</item>
</header2>
<header2>
<item>5</item>
<item>6</item>
<item>7</item>
</header2>
</root>
将此转换应用于同一XML文档(如上)时,会产生相同的正确结果:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kFollowing" match="item"
use="generate-id(preceding-sibling::header[1])"/>
<xsl:template match="/*">
<root>
<xsl:apply-templates select="header"/>
</root>
</xsl:template>
<xsl:template match="header">
<heather2>
<xsl:copy-of select="key('kFollowing', generate-id())"/>
</heather2>
</xsl:template>
</xsl:stylesheet>
<root>
<header/>
<item>1</item>
<item>2</item>
<item>3</item>
<header/>
<item>5</item>
<item>6</item>
<item>7</item>
</root>
<root>
<heather2>
<item>1</item>
<item>2</item>
<item>3</item>
</heather2>
<heather2>
<item>5</item>
<item>6</item>
<item>7</item>
</heather2>
</root>
<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="/*">
<root>
<xsl:for-each-group select="item"
group-adjacent=
"generate-id(preceding-sibling::header[1])">
<header2>
<xsl:sequence select="current-group()"/>
</header2>
</xsl:for-each-group>
</root>
</xsl:template>
</xsl:stylesheet>
<root>
<header2>
<item>1</item>
<item>2</item>
<item>3</item>
</header2>
<header2>
<item>5</item>
<item>6</item>
<item>7</item>
</header2>
</root>
1.
2.
3.
5.
6.
7.
解释:对每个组使用
xsl:。可能会有一个比当前接受的解决方案更简单、更高效的解决方案。还添加了一个XSLT 2.0解决方案。为两个解决方案中的每一个都添加了说明。