Saravanan
Saravanan

Reputation: 11592

How to do I retrieve a particular XML element based on its child elements in XSLT 2.0?

This is my XML Document (small snippet).

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">

<w:body>
    <w:p> <!-- Current Node -->
        <w:r>
            <w:t>
                 This is the
            </w:t>
        </w:r>
        <w:r>
            <w:pict>
                <w:p>
                    <w:r>
                        <w:t>
                            I dont need this
                        </w:t>
                    </w:r>
                </w:p>
            </w:pict>
        </w:r>

        <w:r>
            <w:pict>
                <w:p>
                    <w:r>
                        <w:t>
                            I dont need this too
                        </w:t>
                    </w:r>
                </w:p>
            </w:pict>
        </w:r>

        <w:r>
            <w:t>
                 text that i need to retrieve...
            </w:t>
        </w:r>
    </w:p>
</w:body>
</w:document>   

Here, I want to retrieve <w:r><w:t> value and that <w:r> should not contain child <w:pict> inside it. So, as per my above XML Document I want to generate the following output:

<paragraph>This is the text that i need to retrieve...</paragraph>

and this is my XSLT snippet (please tell me what changes does this XSLT require to get above format):

<xsl:choose>
    <xsl:when test="self::w:p[//w:r/w:t[not(ancestor::w:pict)]]">

        <Paragraph>
            <xsl:apply-templates select="./w:t[not(ancestor::w:pict)]" />
        </Paragraph>
    </xsl:when>
</xsl:choose>

<xsl:template match="w:t">
    <xsl:value-of select="." />
</xsl:template>

but it is not working...

Please guide me to get out of this issue.

Upvotes: 0

Views: 233

Answers (3)

First Zero
First Zero

Reputation: 22356

You can also use filtering to retrieve all w:r nodes which do not have w:pict element

<xs:for-each select="//w:r[count(w:pict) = 0]">
    <xsl:value-of select="w:paragraph" />
</xsl:for-each>

Upvotes: 0

Michael Kay
Michael Kay

Reputation: 163262

Assuming you are processing this in classic XSLT fashion using top-down recursive descent with xsl:apply-templates, then the way to exclude a w:r that has a w:pict child is like this:

<xsl:template match="w:r[w:pict]"/>

I seem to remember coming across a case where I wanted to exclude a w:r if its only child element was a w:pict. In that case the solution would be

<xsl:template match="w:r[w:pict and count(*)=1]"/>

Upvotes: 1

Per T
Per T

Reputation: 2038

In your current example, if your current node is /w:document/w:body/w:p you can retrive all your desired nodes with:

w:r/w:t

However, if you need to retrive w:r/w:t on any level but with out w:pict as ancestor, you could use the ancestor axis as such:

.//w:r/w:t[not(ancestor::w:pict)]

Upvotes: 1

Related Questions