在处理Xpath表达式时,我遇到了一个案例,我必须找出该节点,该节点依赖于另一个节点的一个元素。
以下是使用的XML示例:
<?xml version="1.0" encoding="UTF-8" ?>
<parent1>
<child1 id="1">
<in>Starting1</in>
<out>connect1</out>
</child1>
<child1 id="2">
<in>connect1</in>
<out>connect1.1</out>
</child1>
<child1 id="3">
<in>Starting2</in>
<out>connect2</out>
</child1>
<child1 id="4">
<in>connect1.1</in>
<out>connect1.2</out>
</child1>
<child1 id="5">
<in>connect1.2</in>
<out>end1</out>
</child1>
<child1 id="6">
<in>connect2</in>
<out>connect2.1</out>
</child1>
<child1 id="7">
<in>connect2.1</in>
<out>connect2.2</out>
</child1>
<child1 id="8">
<in>connect2.2</in>
<out>open2</out>
</child1>
</parent1>
期望的输出是找出节点,其起点为&#34;开始&#34;然后前往另一个节点(意味着,节点外是In用于其他节点)&amp;结束于&#34;结束&#34;。
在开始和结束之间可能有x个连接。
我使用了以下xpath表达式。但这仅限于2级递归。
//parent1/child1[in=(//parent1/child1[in=(//parent1/child1[in=(//parent1/child1[contains(in,"Starting")]/out)]/out)]/out) and not(contains(out,"end"))]
输出:
<child1 id="8">
<in>connect2.2</in>
<out>open2</out>
</child1>
因为,我不确定节点之间可以连接多少个连接器。那么,在XML1.0中是否有任何方法可以找出递归?
有一个duplicate question already in stackoverflow.但是,我没有从那里得到解决方案。
答案 0 :(得分:1)
您的要求不是很清楚。从我认为我明白的一点点来看,我相信你必须在两次通过中做到这一点。这是一个局部的例子:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="edge-by-in" match="child1" use="in" />
<xsl:key name="edge-by-out" match="child1" use="out" />
<xsl:template match="/parent1">
<xsl:variable name="first-pass">
<xsl:for-each select="child1">
<edge id="{@id}">
<xsl:apply-templates select="." mode="find-start"/>
<xsl:apply-templates select="." mode="find-end"/>
</edge>
</xsl:for-each>
</xsl:variable>
<output>
<!-- process the nodes contained in $first-pass -->
</output>
</xsl:template>
<xsl:template match="child1" mode="find-start">
<xsl:variable name="prev" select="key('edge-by-out', in)" />
<xsl:choose>
<xsl:when test="$prev">
<xsl:apply-templates select="$prev" mode="find-start"/>
</xsl:when>
<xsl:otherwise>
<start>
<xsl:value-of select="in"/>
</start>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="child1" mode="find-end">
<xsl:variable name="next" select="key('edge-by-in', out)" />
<xsl:choose>
<xsl:when test="$next">
<xsl:apply-templates select="$next" mode="find-end"/>
</xsl:when>
<xsl:otherwise>
<end>
<xsl:value-of select="out"/>
</end>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
将此值应用于输入时,$first-pass
变量将包含:
<edge id="1">
<start>Starting1</start>
<end>end1</end>
</edge>
<edge id="2">
<start>Starting1</start>
<end>end1</end>
</edge>
<edge id="3">
<start>Starting2</start>
<end>open2</end>
</edge>
<edge id="4">
<start>Starting1</start>
<end>end1</end>
</edge>
<edge id="5">
<start>Starting1</start>
<end>end1</end>
</edge>
<edge id="6">
<start>Starting2</start>
<end>open2</end>
</edge>
<edge id="7">
<start>Starting2</start>
<end>open2</end>
</edge>
<edge id="8">
<start>Starting2</start>
<end>open2</end>
</edge>
现在,您可以使用它来选择具有(或不具有)特定start
或end
的节点。
答案 1 :(得分:0)