Mike
Mike

Reputation: 616

XPath - Return child nodes but not descendants

I have the following XML.

<Programme>
    <Intakes>
        <One>
            <Information />
        </One>
        <Two>
            <Information />
        </Two>
    </Intakes>
</Programme>

Wanted result information inside the listbox:

One
Two

Basically I wish to populate a list box with an option for each intake (one, two, etc).

does not have multiple occurances.

So I do not get individual intakes child nodes?

Current code:

        XPathNavigator nav;
        XPathDocument docNav;
        XPathNodeIterator NodeIter;
        string strExpression;

        docNav = new XPathDocument(docPath);
        nav = docNav.CreateNavigator();

        strExpression = "//Intakes/node()";
        NodeIter = nav.Select(strExpression);

        while (NodeIter.MoveNext())
        {
            lstIntakes.Items.Add(NodeIter.Current.Value);
        }

However this only adds one item to the listbox containing all the xml from inside the node.

Upvotes: 1

Views: 988

Answers (1)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243579

XPath is a query language for XML documents and as such it cannot alter the structure of a document.

XSLT is a proper tool for transforming an XML document into another. The XSLT solution of this problem is:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="/*"><xsl:apply-templates/></xsl:template>
 <xsl:template match="One/node()|Two/node()"/>
</xsl:stylesheet>

When this transformation is applied on the provided XML document:

<Programme>
    <Intakes>
        <One>
            <Information />
        </One>
        <Two>
            <Information />
        </Two>
    </Intakes>
</Programme>

the wanted, correct result is produced:

<Intakes>
   <One/>
   <Two/>
</Intakes>

UPDATE: The OP has changed the question radically -- now the wanted result is:

One  
Two 

This still cannot be provided by a single XPath 1.0 expression (and as you are using C#, you probably don't have access to an XPath 2.0 implementation).

You have first to select all children elements of Intakes:

/*/Intakes/*

Then you have to iterate through the returned node-set and for each element contained in it evaluate this XPath expression:

name()

Upvotes: 4

Related Questions