Fazer uma PerguntaFazer uma Pergunta
 

Respondidoxml selectsinglenode

  • sexta-feira, 6 de novembro de 2009 19:15Rohrer Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     Contém Código
    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,

Respostas

  • segunda-feira, 9 de novembro de 2009 13:33Wyck Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     RespondidoContém Código
    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.
    • Marcado como RespostaRohrer segunda-feira, 9 de novembro de 2009 16:42
    •  

Todas as Respostas

  • sexta-feira, 6 de novembro de 2009 19:33Wyck Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     
    Sorry...

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

    • EditadoWyck sexta-feira, 6 de novembro de 2009 19:37misunderstood
    •  
  • sábado, 7 de novembro de 2009 7:59Jai Mallesh Babu Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     Contém Código
    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);
    }
    


  • domingo, 8 de novembro de 2009 20:44Rohrer Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     Contém Código
    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



  • domingo, 8 de novembro de 2009 21:07Yort Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     
    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.
  • domingo, 8 de novembro de 2009 21:17Rohrer Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     
    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.


  • domingo, 8 de novembro de 2009 21:28Yort Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     
    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.
  • segunda-feira, 9 de novembro de 2009 5:31Jai Mallesh Babu Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     
    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
  • segunda-feira, 9 de novembro de 2009 12:50Rohrer Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     
    I would love to use linq, except currently we are only supporting 2.0. :(
  • segunda-feira, 9 de novembro de 2009 13:33Wyck Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     RespondidoContém Código
    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.
    • Marcado como RespostaRohrer segunda-feira, 9 de novembro de 2009 16:42
    •