如何使用 XPath 从 XML 中检索递归元素
How to retrive recursive element from XML using XPath
在处理 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>
期望的输出是找出起点为 "Starting" 的节点,然后前往另一个节点(意味着,对于其他节点,节点外是 In)并且不以 [=35 结束=].
开始和结束之间可能有 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 Whosebug. 但是,我没有从那里得到解决方案。
//parent1/child1[包含(in/text(), 'Starting') 而不是(包含(out/text(), 'end'))]
更新
看图片。它 returns 正是您所要求的:
Desired output is to find out the node, which is having starting point
as "Starting" & Not ending in "end".
你能用你的期望更新你的问题吗?也许你希望使用你添加的 XML 的输出。
你的要求不是很清楚。从我认为我理解的一点点来看,我相信你必须在两个 passes.Here 的部分示例中做到这一点:
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>
现在您可以将其用于 select 个具有(或不具有)特定 start
或 end
的节点。
在处理 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>
期望的输出是找出起点为 "Starting" 的节点,然后前往另一个节点(意味着,对于其他节点,节点外是 In)并且不以 [=35 结束=].
开始和结束之间可能有 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 Whosebug. 但是,我没有从那里得到解决方案。
//parent1/child1[包含(in/text(), 'Starting') 而不是(包含(out/text(), 'end'))]
更新
看图片。它 returns 正是您所要求的:
Desired output is to find out the node, which is having starting point as "Starting" & Not ending in "end".
你能用你的期望更新你的问题吗?也许你希望使用你添加的 XML 的输出。
你的要求不是很清楚。从我认为我理解的一点点来看,我相信你必须在两个 passes.Here 的部分示例中做到这一点:
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>
现在您可以将其用于 select 个具有(或不具有)特定 start
或 end
的节点。