xslt - How to retrive recursive element from XML using XPath -
while working on xpath expressions, stuck in 1 case, have find out node, dependent on other node's 1 element.
below xml example used :
<?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>
desired output find out node, having starting point "starting" , travel node ( means, out of node in other node) & not ending in "end".
there might x number of connections between starting , end.
i have used following xpath expression. limited 2 level of recursion.
//parent1/child1[in=(//parent1/child1[in=(//parent1/child1[in=(//parent1/child1[contains(in,"starting")]/out)]/out)]/out) , not(contains(out,"end"))]
output :
<child1 id="8"> <in>connect2.2</in> <out>open2</out> </child1>
as, not sure how many number of connectors between nodes. so, there way in xml1.0 find out recursion?
there duplicate question in stackoverflow. but, didn't solution there.
your requirement not clear. little think understand, believe have in 2 passes.here's partial example:
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 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>
when apply input, $first-pass
variable contain:
<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>
now can use select nodes have (or don't have) particular start
or end
.
Comments
Post a Comment