Ask a questionAsk a question
 

Answerxml selectsinglenode

  • Friday, November 06, 2009 7:15 PMRohrer Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Hello,

    I have this xml

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <soapenv:Header/>
        <soapenv:Body>
            <SessionID xmlns="http://www.niku.com/xog">11938473__567b131:124c40c66bc:-7f361257534325686</SessionID>
        </soapenv:Body>
    </soapenv:Envelope>
    
    I would like to select the SessionID node.  I thought the syntax was would be

    Dim xmlDoc As New XmlDocument
    xmlDoc.LoadXml(xml)
    
    Dim node As XmlNode = xmlDoc.SelectSingleNode("descendant::SessionID")
    
    Can someone please help me with the syntax.

    Thank you,

Answers

  • Monday, November 09, 2009 1:33 PMWyck Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     AnswerHas Code
    Sorry again, I totally misunderstood your problem a couple of times.  I think you are having problems with the fact that XPath does not support anonymous namespaces.  You put SessionID into an anonymous namespace with the xmlns="http://www.niky.com/xog" namespace attribute.  In your query, use an XmlNamespaceManager to assign an actual name to that namespace, and use that name in your XPath.  The name can be anything.  Here, I will provide an example, giving the anonymous namespace the name foo .
    class Program
    {
    	static void Main( string[] args )
    	{
    		string xml =
    @"<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>
        <soapenv:Header/>
        <soapenv:Body>
            <SessionID xmlns='http://www.niku.com/xog'>11938473__567b131:124c40c66bc:-7f361257534325686</SessionID>
        </soapenv:Body>
    </soapenv:Envelope>";
    		XmlDocument doc = new XmlDocument();
    		doc.LoadXml( xml );
    		XmlNamespaceManager nsmgr = new XmlNamespaceManager( doc.NameTable );
    		nsmgr.AddNamespace( "foo", "http://www.niku.com/xog" );
    		XmlNode node = doc.SelectSingleNode( "descendant::foo:SessionID", nsmgr );
    		Console.WriteLine( node.Name );
    	}
    }
    
    

    Hopefully now I'm on the same page as you!

    Note that your xpath syntax has changed from
        descendant::SessionID
    to
        descendant::foo:SessionID

    Note the use of a double colon for axis specifier and single colon for namespace separator.
    • Marked As Answer byRohrer Monday, November 09, 2009 4:42 PM
    •  

All Replies

  • Friday, November 06, 2009 7:33 PMWyck Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Sorry...

    Try "//SessionID"
    or "/*/*/SessionID"

    • Edited byWyck Friday, November 06, 2009 7:37 PMmisunderstood
    •  
  • Saturday, November 07, 2009 7:59 AMJai Mallesh Babu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    How to query XML with an XPath expression by using Visual C#:

    http://support.microsoft.com/default.aspx/kb/308333

    XPathNavigator Class
    Provides a cursor model for navigating and editing XML data:
    http://msdn.microsoft.com/en-us/library/system.xml.xpath.xpathnavigator.aspx


    XPathNavigator Select Method (XPathExpression)

    http://msdn.microsoft.com/en-us/library/3tk3f03k.aspx


    The following example uses the Select method to select a node set.

    Visual Basic
    Dim document As XPathDocument = New XPathDocument("books.xml")
    Dim navigator As XPathNavigator = document.CreateNavigator()
    
    Dim query As XPathExpression = navigator.Compile("/bookstore/book")
    Dim nodes As XPathNodeIterator = navigator.Select(query)
    Dim nodesNavigator As XPathNavigator = nodes.Current
    
    Dim nodesText As XPathNodeIterator = nodesNavigator.SelectDescendants(XPathNodeType.Text, False)
    
    While nodesText.MoveNext()
        Console.WriteLine(nodesText.Current.Value)
    End While
    
    C#
    XPathDocument document = new XPathDocument("books.xml");
    XPathNavigator navigator = document.CreateNavigator();
    
    XPathExpression query = navigator.Compile("/bookstore/book");
    XPathNodeIterator nodes = navigator.Select(query);
    XPathNavigator nodesNavigator = nodes.Current;
    
    XPathNodeIterator nodesText = nodesNavigator.SelectDescendants(XPathNodeType.Text, false);
    
    while (nodesText.MoveNext())
    {
        Console.WriteLine(nodesText.Current.Value);
    }
    


  • Sunday, November 08, 2009 8:44 PMRohrer Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    I am confused about this.  I haven't ever had to use xpathnavigator to select nodes.

    This is a example of the xml I am dealing with:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <soapenv:Header/>
        <soapenv:Body>
            <ReadTimeperiodResponse xmlns="http://www.niku.com/xog/Object">
                <NikuDataBus
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../xsd/nikuxog_timeperiod.xsd">
                    <Header externalSource="NIKU" version="8.1.4.4573"/>
                    <TimePeriods/>
                    <XOGOutput>
                        <Object type="timeperiod"/>
                        <Status state="SUCCESS"/>
                        <Statistics failureRecords="0" insertedRecords="0"
                            totalNumberOfRecords="0" updatedRecords="0"/>
                        <Records/>
                        <DeprecationInformation>
                            <Severity>WARNING</Severity>
                            <Description>DEPRECATION MESSAGE</Description>
                            <Exception type="java.lang.Exception">The action and objectType attributes in the Header have been deprecated.</Exception>
                        </DeprecationInformation>
                    </XOGOutput>
                </NikuDataBus>
            </ReadTimeperiodResponse>
        </soapenv:Body>
    </soapenv:Envelope>
    
    When I run the following code:

    Dim doc As New XmlDocument
    doc.LoadXml(responseText)

    Dim testList As XmlNodeList = doc.SelectNodes("//*")

    It finds the following xml elements:

    soapenv:Envelope
    soapenv:Header
    soapenv:Body
    ReadTimeperiodResponse
    NikuDataBus
    Header
    TimePeriods
    XOGOutput
    Object
    Status
    Statistics
    Records
    DeprecationInformation
    Severity
    Description
    Exception

    If you look at the list, you can see that XOGOutput is in the list.

    Now if I run this following code:

    Dim doc As New XmlDocument
    doc.LoadXml(responseText)

    Dim testList As XmlNodeList = doc.SelectNodes("//XOGOutput/*")

    I get no results.  Which makes no sense to me, because it should find any elements with the name of XOGOutput.  It should return 1 element.

    Any help would be appreciated.

    Thank you



  • Sunday, November 08, 2009 9:07 PMYort Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi,

    Actually

    Dim testList As XmlNodeList = doc.SelectNodes("//XOGOutput/*")

    should return

    Object
    Status
    Statistics
    Records
    DeprecationInformation

    Since you are selecting the sub nodes of XOGOutput (the /* means all nodes at the level below the previous node which is XOGOutput).

    I'm not sure, but I think the zero result might be caused by multiple namespaces in the xml. You might have to use a System.Xml.XmlNamespaceManager with the SelectNodes method, but I'm not entirely sure how to set it up correctly.
  • Sunday, November 08, 2009 9:17 PMRohrer Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I believe that is part of the problem. 

    When I check doc.NameSpaceURI, it is string.empty.  The doc.NameTable is also empty, which means the xml doesn't have any namespaces. 

    Why would this occur?  If you view the xml, it clearly has namespaces.


  • Sunday, November 08, 2009 9:28 PMYort Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I'm afraid I don't know, most Xml I work with doesn't have namespaces so I haven't encountered this before.

    I suspect that while the Xml has namespaces embedded in it, that doesn't automatically cause the objects you're reading to fetch the schema's/map the namespaces etc. and that you are still required to either set them up manually, or start some process to tell the system it's ok to do those things.
  • Monday, November 09, 2009 5:31 AMJai Mallesh Babu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    LINQ is another good option for you.

    Short method:

    instantiate  XDocument.

    Use XDocument.Parse(<Your XML String>);

    var sessiond= from myXml in <Your XDocument created aboe> select myXml.Element("SessionID").Value;


    Querying XML in C# with LINQ to XML:
    http://www.microsoft.com/uk/msdn/nuggets/nugget/204/querying-xml-in-c-with-linq-to-xml.aspx

    Regards,
    Jai
  • Monday, November 09, 2009 12:50 PMRohrer Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I would love to use linq, except currently we are only supporting 2.0. :(
  • Monday, November 09, 2009 1:33 PMWyck Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     AnswerHas Code
    Sorry again, I totally misunderstood your problem a couple of times.  I think you are having problems with the fact that XPath does not support anonymous namespaces.  You put SessionID into an anonymous namespace with the xmlns="http://www.niky.com/xog" namespace attribute.  In your query, use an XmlNamespaceManager to assign an actual name to that namespace, and use that name in your XPath.  The name can be anything.  Here, I will provide an example, giving the anonymous namespace the name foo .
    class Program
    {
    	static void Main( string[] args )
    	{
    		string xml =
    @"<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>
        <soapenv:Header/>
        <soapenv:Body>
            <SessionID xmlns='http://www.niku.com/xog'>11938473__567b131:124c40c66bc:-7f361257534325686</SessionID>
        </soapenv:Body>
    </soapenv:Envelope>";
    		XmlDocument doc = new XmlDocument();
    		doc.LoadXml( xml );
    		XmlNamespaceManager nsmgr = new XmlNamespaceManager( doc.NameTable );
    		nsmgr.AddNamespace( "foo", "http://www.niku.com/xog" );
    		XmlNode node = doc.SelectSingleNode( "descendant::foo:SessionID", nsmgr );
    		Console.WriteLine( node.Name );
    	}
    }
    
    

    Hopefully now I'm on the same page as you!

    Note that your xpath syntax has changed from
        descendant::SessionID
    to
        descendant::foo:SessionID

    Note the use of a double colon for axis specifier and single colon for namespace separator.
    • Marked As Answer byRohrer Monday, November 09, 2009 4:42 PM
    •