以下面的XML为例:
<?xml version="1.0" encoding="UTF-8"?>
<HelloXml>
<Greeting>Hello</Greeting>
<Name>World</Name>
<FriendList>
<Friend>
<Number>1</Number>
<BestFriend id='start' />
</Friend>
<Friend>
<Number>2</Number>
<Name>Mercury</Name>
</Friend>
<Friend>
<Number>3</Number>
<BestFriend id='end' />
</Friend>
<Friend>
<Number>4</Number>
<Name>Venus</Name>
</Friend>
<!-- ... -->
<Friend>
<Number>7</Number>
<BestFriend id='start' />
</Friend>
<Friend>
<Number>8</Number>
<Name>Saturn</Name>
</Friend>
<!-- ... -->
<Friend>
<Number>11</Number>
<BestFriend id='end' />
</Friend>
<!-- ... -->
<Friend>
<Number>12</Number>
<Name>Neptune</Name>
</Friend>
</FriendList>
</HelloXml>
我需要做几件事:
想法是输出类似于:
<BestFriends>
<Friend number='1'>
<Name>Mercury</Name>
</Friend>
<Friend number='2'>
<Name>Saturn</Name>
</Friend>
</BestFriends>
我尝试过使用下一个兄弟,先前兄弟和其他逻辑,但到目前为止,没有运气。
欢迎任何建议。
感谢。
编辑:对不起,我搞砸了“结束”的旗帜。此外,我们正在使用XSLT 1.0。 编辑:现在需求已经改变,而且比以前更令人困惑。情况是一样的,但现在输出应该是这样的:<?xml version="1.0" encoding="UTF-8"?>
<FriendList>
<Friend BestFriend="true">
<Name>Mercury</Name>
</Friend>
<Friend BestFriend="false">
<Name>Venus</Name>
</Friend>
<Friend BestFriend="true">
<Name>Saturn</Name>
</Friend>
<Friend BestFriend="false">
<Name>Neptune</Name>
</Friend>
</FriendList>
为了将要求用语言表达,我需要不加歧视地输出所有“朋友”,但我需要添加一个属性来区分“BestFriends”和普通的“BestFriends”。这些BestFriends都是“开始/结束”标志内的所有内容。
@ michael.hor257k提供的先前解决方案非常酷且乐于助人(再次感谢man!),但我的用户更改了要求:/
我已尝试对“兄弟递归”方法进行一些修改,也尝试了一些“循环”(但这不是java,当然,它不起作用),并使用一些变量(在XSLT中是常量) ,所以它也不起作用。)
欢迎任何帮助!
答案 0 :(得分:0)
假设您正在使用XSLT 1.0,并进一步假设您的输入示例不正确,您可以使用以下样式表基于称为&#34;兄弟递归&#34;的技术:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/HelloXml">
<BestFriends>
<xsl:apply-templates select="FriendList/Friend[BestFriend/@id='start']/following-sibling::Friend[1]"/>
</BestFriends>
</xsl:template>
<xsl:template match="Friend">
<Friend number="{Number}">
<xsl:copy-of select="Name"/>
</Friend>
<xsl:apply-templates select="following-sibling::Friend[1][not(BestFriend/@id='end')]" />
</xsl:template>
</xsl:stylesheet>
应用于以下测试输入:
<HelloXml>
<Greeting>Hello</Greeting>
<Name>World</Name>
<FriendList>
<Friend>
<Number>0</Number>
<Name>Sun</Name>
</Friend>
<Friend>
<Number>1</Number>
<BestFriend id="start"/>
</Friend>
<Friend>
<Number>2</Number>
<Name>Mercury</Name>
</Friend>
<Friend>
<Number>3</Number>
<BestFriend id="end"/>
</Friend>
<Friend>
<Number>7</Number>
<BestFriend id="start"/>
</Friend>
<Friend>
<Number>8</Number>
<Name>Saturn</Name>
</Friend>
<Friend>
<Number>9</Number>
<Name>Pluto</Name>
</Friend>
<Friend>
<Number>10</Number>
<BestFriend id="end"/>
</Friend>
<Friend>
<Number>11</Number>
<Name>Moon</Name>
</Friend>
</FriendList>
</HelloXml>
结果将是:
<?xml version="1.0" encoding="UTF-8"?>
<BestFriends>
<Friend number="2">
<Name>Mercury</Name>
</Friend>
<Friend number="8">
<Name>Saturn</Name>
</Friend>
<Friend number="9">
<Name>Pluto</Name>
</Friend>
</BestFriends>
请注意,这假设 start 和 end 标志节点之间至少有一个Friend
节点。
我需要输出所有&#34;朋友&#34;没有歧视,但我需要 添加一个属性来区分&#34; BestFriends&#34;从正常 那些。这些BestFriends都是其中的所有内容 &#34;开始/结束&#34;标志。
有一种非常简单的方法可以实现这一目标,但效率不高:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/HelloXml">
<FriendList>
<xsl:for-each select="FriendList/Friend[Name]">
<Friend BestFriend="{count(preceding-sibling::Friend[BestFriend[@id='start']]) != count(preceding-sibling::Friend[BestFriend[@id='end']])}">
<xsl:copy-of select="Name"/>
</Friend>
</xsl:for-each>
</FriendList>
</xsl:template>
</xsl:stylesheet>
如果输入较大,您可能需要先考虑预处理最好的朋友(或不是最好的朋友),然后使用列表确定输出中BestFriend属性的值。