tags:

views:

33

answers:

1

How do i select all the text nodes within a specific element node using XSL?

Input xml:

 <node1 id="1">
 <node2 id="2">
 <node3 id="3" />
 <node4 id="4">
 <node5 id="5">Text node1</node5>
 <node6 id="6">Text node2</node6>
 </node4>
 </node2>
 <node7 id="7">Text node3
 <node8 id="8">Text node4</node8>
 <node9 id="9">Text node5</node9>
 </node7>
 <node10 id="10">Text node6</node10>
 <node11 id="11">Text node3
 <node12 id="12">Text node4</node12>
 <node13 id="13">Text node5</node13>
 </node11>
 </node1>

Input Param: List of ids of the element nodes whose txt nodes are to be retrieved.

 <nodes><node>4</node><node>7</node><node>10</node></nodes>

Expected Output:

Text node1

Text node2

Text node3

Text node4

Text node5

Text node6

How can this be achieved using XSL? Please share your ideas.

+2  A: 

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common"
 >
 <xsl:output method="text"/>

 <xsl:strip-space elements="*"/>

 <xsl:param name="pNodes">
    <nodes>
        <node>4</node>
        <node>7</node>
        <node>10</node>
    </nodes>
 </xsl:param>

 <xsl:variable name="vNodes"
 select="ext:node-set($pNodes)/*/*"/>

 <xsl:template match="/">
   <xsl:for-each select=
      "//*[substring-after(name(),'node')
          = $vNodes
           ]
            //text()">

   <xsl:value-of select="concat(.,'&#xA;')"/>
 </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<node1 id="1">
    <node2 id="2">
        <node3 id="3" />
        <node4 id="4">
            <node5 id="5">Text node1</node5>
            <node6 id="6">Text node2</node6>
        </node4>
    </node2>
    <node7 id="7">Text node3
        <node8 id="8">Text node4</node8>
        <node9 id="9">Text node5</node9>
    </node7>
    <node10 id="10">Text node6</node10>
    <node11 id="11">Text node3
        <node12 id="12">Text node4</node12>
        <node13 id="13">Text node5</node13>
    </node11>
</node1>

produces the wanted result:

Text node1
Text node2
Text node3
Text node4
Text node5
Text node6
Dimitre Novatchev
When i run it in Java SAXON processor, it gives the error, Cannot find a matching 1-argument function named {http://exslt.org/common}node-set()
@user323719: You are using Saxon9.x which is an XSLT 2.0 processor. In XSLT 2.x you don't need the `xxx:node-set()` function -- just remove it, and use: `<xsl:variable name="vNodes" select="$pNodes/*/*"/>`
Dimitre Novatchev
Thanks it works.