Answered SelectSingleNode() function returns null

  • Tuesday, June 17, 2008 11:59 AM
     
     

    I am developing a program for reading RDL files (Reporting Services Report Files). Assume my XML is the following:

     

    <?xml version="1.0" encoding="utf-8"?>

    <Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">

      <DataSources>

        <DataSource Name="DataSource">

          <ConnectionProperties>

            <IntegratedSecurity>true</IntegratedSecurity>

            <ConnectString></ConnectString>

            <DataProvider></DataProvider>

          </ConnectionProperties>

          <rdBig SmileataSourceID>136c762c-789b-4fa7-b4a8-b60c584c387b</rdBig SmileataSourceID>

        </DataSource>

      </DataSources>

      <BottomMargin>2.5cm</BottomMargin>

      <RightMargin>2.5cm</RightMargin>

      <rdBig SmilerawGrid>true</rdBig SmilerawGrid>

      <InteractiveWidth>8.5in</InteractiveWidth>

      <rd:GridSpacing>0.25cm</rd:GridSpacing>

      <rdTongue TiednapToGrid>true</rdTongue TiednapToGrid>

    .

    .

    .

    </Report>

     

    When I write the following code to get the "DataSources" Node, the SelectSingleNode() function returns null:

     

    doc.SelectSingleNode("DataSources")

    or

    doc.DocumentElement.SelectSingleNode("DataSources")

    or

    doc.SelectSingleNode("//DataSources")

    or

    doc.DocumentElement.SelectSingleNode("//DataSources")

    or

    doc.SelectSingleNode("/DataSources")

    or

    doc.DocumentElement.SelectSingleNode("/DataSources")

     

     

    why?

Answers

  • Tuesday, June 17, 2008 12:22 PM
     
     Answered

    There is a default namespace declaration you need to take into account by using an XmlNamespaceManager as follows:

    Code Snippet

    Dim doc As New XmlDocument()

    doc.Load("file.xml")

    Dim mgr As New XmlNamespaceManager(doc.NameTable)

    mgr.AddNamespace("df", "http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition")

    Dim node As XmlNode = doc.SelectSingleNode("/df:Report/df:DataSources", mgr)

     

     

  • Tuesday, July 08, 2008 4:22 PM
     
     Answered

    That element is down in the document so you either need to give the full path or you need to use // in your XPath e.g.

    Code Snippet

    //ACORD:InsuranceSvcRq

     

     

    The full path looks like

    Code Snippet

    /ACORD:ACORD/ACORD:InsuranceSvcRq

     

     

    As a third alternative, as you call SelectSingleNode on the DocumentElement (my sample calls it on the document node), you could use

    ACORD:InsuranceSvcRq

    without a leading slash.

All Replies

  • Tuesday, June 17, 2008 12:22 PM
     
     Answered

    There is a default namespace declaration you need to take into account by using an XmlNamespaceManager as follows:

    Code Snippet

    Dim doc As New XmlDocument()

    doc.Load("file.xml")

    Dim mgr As New XmlNamespaceManager(doc.NameTable)

    mgr.AddNamespace("df", "http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition")

    Dim node As XmlNode = doc.SelectSingleNode("/df:Report/df:DataSources", mgr)

     

     

  • Tuesday, July 08, 2008 4:11 PM
     
     

    I am still having the problem with this method returning null.  I've recreated Martin's example. 
    My XML is below:

    Code Snippet

    <?xml version="1.0" encoding="utf-8"?>

    <ACORD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.ACORD.org/standards/PC_Surety/ACORD1.4.1/xml/">

    <SignonRq>

    <ClientApp>

    <Org>Online</Org>

    </ClientApp>

    </SignonRq>

    <InsuranceSvcRq>

    <RqUID>00000000-0000-0000-0000-001030582207</RqUID>

    <PersAutoPolicyQuoteInqRq>

    <RqUID>00000000-0000-0000-0000-001030582207</RqUID>

    <PersPolicy>

    <ContractTerm>

    <EffectiveDt>2008-07-08</EffectiveDt>

    </ContractTerm>

    </PersPolicy>

    </PersAutoPolicyQuoteInqRq>

    </InsuranceSvcRq>

    </ACORD>

     

    And my code, which throws an exception every time:

    Code Snippet

    static void Main(string[] args)

    {

    XmlDocument doc = new XmlDocument();

    doc.Load("my.xml");

    XmlNamespaceManager xnm = new XmlNamespaceManager(doc.NameTable);

    xnm.AddNamespace("ACORD", "http://www.ACORD.org/standards/PC_Surety/ACORD1.4.1/xml/");

    XmlNode node = doc.DocumentElement.SelectSingleNode("/ACORD:InsuranceSvcRq", xnm);

    if (node == null)

    throw new NullReferenceException();

    }

     

  • Tuesday, July 08, 2008 4:22 PM
     
     Answered

    That element is down in the document so you either need to give the full path or you need to use // in your XPath e.g.

    Code Snippet

    //ACORD:InsuranceSvcRq

     

     

    The full path looks like

    Code Snippet

    /ACORD:ACORD/ACORD:InsuranceSvcRq

     

     

    As a third alternative, as you call SelectSingleNode on the DocumentElement (my sample calls it on the document node), you could use

    ACORD:InsuranceSvcRq

    without a leading slash.

  • Tuesday, July 08, 2008 4:44 PM
     
     

    Outstanding - that works great!  I found this notation to be the most helpful:

    Code Snippet

    //ACORD:InsuranceSvcRq

     

    Because it simply searches for that element, you don't have to specify the full path.  Thanks for your help.

  • Tuesday, July 08, 2008 4:51 PM
     
     

    But note that using // is expensive as it searches through the whole document. It does not matter for small documents but if you have large documents you might want to avoid using // in your XPath expressions if you can write a more precise XPath expression.