我需要写一个相当复杂的条件。我将在这个例子中解释:
<document>
<para>
<wd>Hello</wd>
<wd>Stackoverflow</wd>
</para>
<para>
<run>
<wd> PO23135153 </wd>
<wd> text and numb3rs </wd>
<wd> 312.000 </wd>
<wd> moar stuff </wd>
</run>
<wd> PO3213213 </wd>
<wd> blah </wd>
<wd> 1000.000 </wd>
<wd> 000.000 </wd>
</para>
</document>
我需要做的是选择1000.000和312.000
我相信这可以通过在找到包含“PO *”的字符串后找到包含“.000”的第一个字符串来完成。
XML文档的结构可能会有所不同,PO的实例数量和相关的.000s也是如此
我相信这可以部分地在if表达式中使用“position()”和“contains”来实现,但我不能真正将它们组合在一起。
感谢您的帮助
修改
这更接近于我拥有的XML数据:
<document>
<para>
<wd>Hello</wd>
<wd>Stackoverflow</wd>
</para>
<para>
<ln>
<run>
<wd> PO23135153 </wd>
</run>
<run>
<wd> text and numb3rs </wd>
</run>
<run>
<wd> 312.000 </wd>
</run>
<run>
<wd> moar stuff </wd>
</ln>
<ln>
</abc>
<wd> PO3213213 </wd>
</abc>
<abc>
<wd> blah </wd>
</abc>
<abc>
<wd> 1000.000 </wd>
</abc>
<abc>
<wd> 000.000 </wd>
</abc>
</ln>
</para>
</document>
答案 0 :(得分:0)
这会找到想要的wd
元素。如果元素内容中包含“PO”,则它首先匹配wd
,并在结果的part_a
中输出。然后,这一行:
<xsl:value-of select="following-sibling::wd[contains(.,'.000')][1]"/>
找到第一个以下wd
元素,它是一个兄弟,并包含“.000”。限制[1]
是必要的,否则在您的示例中也输出“000.000”。
<强>样式表强>
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="wd[contains(.,'PO')]">
<result>
<part_a>
<xsl:value-of select="."/>
</part_a>
<part_b>
<xsl:value-of select="following-sibling::wd[contains(.,'.000')][1]"/>
</part_b>
</result>
</xsl:template>
<xsl:template match="wd"/>
</xsl:stylesheet>
<强>输出强>
<?xml version="1.0" encoding="UTF-8"?>
<result>
<part_a> PO23135153 </part_a>
<part_b> 312.000 </part_b>
</result>
<result>
<part_a> PO3213213 </part_a>
<part_b> 1000.000 </part_b>
</result>
您的元素包含尾随空格。您可能希望使用normalize-space()
在输出中阻止此操作。
修改强>:
更改要求后,这是一种明智的方法。定义一个变量来存储wd
,无论它们出现在树中的哪个位置。然后,迭代它们。 @ michael.hor257k 建议的轴的变化。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="wds" select="//wd"/>
<xsl:template match="/">
<xsl:for-each select="$wds">
<xsl:if test="contains(.,'PO')">
<result>
<part_a>
<xsl:value-of select="."/>
</part_a>
<part_b>
<xsl:value-of select="following::wd[contains(.,'.000')][1]"/>
</part_b>
</result>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
但首先,您需要更正更新的XML输入,这是无效的。
请注意,这是我最后一次更新此答案。我不愿意花更多的时间在这上面。请清楚说明您的输入XML之前的 。
答案 1 :(得分:-1)
将问题细分为部分,你就会得到结果。
根据我的理解,您需要的是找到并在第一个<wd>
孩子中拥有'PO'并且另一个<wd>
孩子拥有'.000'
因此,对于表达式的第一部分:
//*[./wd[position()=1 and contains(text(), 'PO')]]
第二部分:
//*[./wd[contains(text(), '.000')]
不,你必须将两者结合起来:
//*[./wd[contains(text(), '.000')] and ./wd[position()=1 and contains(text(), 'PO')]]
这将返回节点:
/document/para
/document/para/run