Simple xpath query with default namespace

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jason Mobarak

    Simple xpath query with default namespace

    Hello --

    I'm attempting to get a handle on how to do xpath queries with
    System.Xml -- so far the biggest hurdle has been how to deal with a
    default namespace. If I use the test xml:

    <?xml version="1.0" encoding="utf-8" ?>
    <thing xmlns="urn:thin g-schema-v1">
    <foo>foo thing</foo>
    <bar>bar thing</bar>
    <baz>baz thing</baz>
    </thing>

    ....everything in the code below fails (as in no nodes are located, when
    3 should be). However, if I remove the xmlns declaration from the
    <thingroot element everything works fine. What am I doing wrong?

    using System;
    using System.Collecti ons.Generic;
    using System.Text;

    namespace XmlTest
    {
    class Program
    {
    static void Main(string[] args)
    {
    const string szXPath = "/thing/*";
    const string szFilename = @"..\..\test-wo-xmlns.xml";

    System.Xml.XmlR eader xmlReader = new
    System.Xml.XmlT extReader(Syste m.IO.File.OpenR ead(szFilename) );

    System.Xml.XmlN amespaceManager xmlNsMgr = new
    System.Xml.XmlN amespaceManager (xmlReader.Name Table);
    xmlNsMgr.AddNam espace(String.E mpty, "urn:thing-schema-v1");

    System.Xml.XPat h.XPathDocument xpath = new
    System.Xml.XPat h.XPathDocument (xmlReader);

    System.Xml.XPat h.XPathNavigato r xpathNavi =
    xpath.CreateNav igator();

    System.Xml.XPat h.XPathNodeIter ator xpathQuery =
    xpathNavi.Selec t(szXPath);
    while(xpathQuer y.MoveNext())
    {
    string szValue = xpathQuery.Curr ent.Value;
    System.Console. WriteLine(szVal ue);
    }

    System.Xml.XPat h.XPathExpressi on xpathExpr =
    xpathNavi.Compi le(szXPath);
    xpathExpr.SetCo ntext(xmlNsMgr) ;

    xpathQuery = xpathNavi.Selec t(xpathExpr);
    while (xpathQuery.Mov eNext())
    {
    string szValue = xpathQuery.Curr ent.Value;
    System.Console. WriteLine(szVal ue);
    }

    System.Xml.XmlD ocument xmlDoc = new
    System.Xml.XmlD ocument();
    xmlDoc.Load(szF ilename);

    System.Xml.XmlN amespaceManager xmlNsMgr2 = new
    System.Xml.XmlN amespaceManager (xmlDoc.NameTab le);
    xmlNsMgr2.AddNa mespace(String. Empty,
    "urn:thing-schema-v1");

    System.Xml.XmlN odeList xmlNodes =
    xmlDoc.SelectNo des(szXPath);

    foreach(System. Xml.XmlNode xmlNode in xmlNodes)
    {
    string szValue = xmlNode.Value;
    System.Console. WriteLine(szVal ue);
    }
    }
    }
    }

  • Jason Mobarak

    #2
    Re: Simple xpath query with default namespace

    I don't quite understand why this works... but as many others have
    probably discovered if you create a namespace manager like so:

    System.Xml.XmlN amespaceManager xmlNsMgr = new
    System.Xml.XmlN amespaceManager (xmlReader.Name Table);
    xmlNsMgr.AddNam espace("q", "urn:thing-schema-v1");

    ....then use a query such as "/q:thing/*" then everything in the code
    below works. Why is this?

    On Dec 2, 11:17 pm, "Jason Mobarak" <jason.moba...@ gmail.comwrote:
    Hello --
    >
    I'm attempting to get a handle on how to do xpath queries with
    System.Xml -- so far the biggest hurdle has been how to deal with a
    default namespace. If I use the test xml:
    >
    <?xml version="1.0" encoding="utf-8" ?>
    <thing xmlns="urn:thin g-schema-v1">
    <foo>foo thing</foo>
    <bar>bar thing</bar>
    <baz>baz thing</baz>
    </thing>
    >
    ...everything in the code below fails (as in no nodes are located, when
    3 should be). However, if I remove the xmlns declaration from the
    <thingroot element everything works fine. What am I doing wrong?
    >
    using System;
    using System.Collecti ons.Generic;
    using System.Text;
    >
    namespace XmlTest
    {
    class Program
    {
    static void Main(string[] args)
    {
    const string szXPath = "/thing/*";
    const string szFilename = @"..\..\test-wo-xmlns.xml";
    >
    System.Xml.XmlR eader xmlReader = new
    System.Xml.XmlT extReader(Syste m.IO.File.OpenR ead(szFilename) );
    >
    System.Xml.XmlN amespaceManager xmlNsMgr = new
    System.Xml.XmlN amespaceManager (xmlReader.Name Table);
    xmlNsMgr.AddNam espace(String.E mpty, "urn:thing-schema-v1");
    >
    System.Xml.XPat h.XPathDocument xpath = new
    System.Xml.XPat h.XPathDocument (xmlReader);
    >
    System.Xml.XPat h.XPathNavigato r xpathNavi =
    xpath.CreateNav igator();
    >
    System.Xml.XPat h.XPathNodeIter ator xpathQuery =
    xpathNavi.Selec t(szXPath);
    while(xpathQuer y.MoveNext())
    {
    string szValue = xpathQuery.Curr ent.Value;
    System.Console. WriteLine(szVal ue);
    }
    >
    System.Xml.XPat h.XPathExpressi on xpathExpr =
    xpathNavi.Compi le(szXPath);
    xpathExpr.SetCo ntext(xmlNsMgr) ;
    >
    xpathQuery = xpathNavi.Selec t(xpathExpr);
    while (xpathQuery.Mov eNext())
    {
    string szValue = xpathQuery.Curr ent.Value;
    System.Console. WriteLine(szVal ue);
    }
    >
    System.Xml.XmlD ocument xmlDoc = new
    System.Xml.XmlD ocument();
    xmlDoc.Load(szF ilename);
    >
    System.Xml.XmlN amespaceManager xmlNsMgr2 = new
    System.Xml.XmlN amespaceManager (xmlDoc.NameTab le);
    xmlNsMgr2.AddNa mespace(String. Empty,
    "urn:thing-schema-v1");
    >
    System.Xml.XmlN odeList xmlNodes =
    xmlDoc.SelectNo des(szXPath);
    >
    foreach(System. Xml.XmlNode xmlNode in xmlNodes)
    {
    string szValue = xmlNode.Value;
    System.Console. WriteLine(szVal ue);
    }
    }
    }
    >
    }

    Comment

    • Mark R. Dawson

      #3
      Re: Simple xpath query with default namespace

      Hi Jason,
      namespaces in XML serve the same purpose as namespace in C#, they are a
      way to distinguish between two items that happen to have the same identifier.
      In XML you may have one XML definition that has a node called <Account
      BankNo="123"whi ch refers to a Bank Account and another node that is also
      called <Account Name="bob"that refers to a Video Rental account, so if both
      nodes are part of the same XML document how could you distinguish between
      them? The namespace allows that since one could be part of the namespace
      http://www.example.org/banking and another http://www.example.org/videorental
      then when you have your XPath query you will need to tell XPath which Account
      element you mean by prefixing the name with the namespace in your query.
      Hence in your example because the node is part of a namespace you need to use
      that information in your XPath query.


      Mark.
      --



      "Jason Mobarak" wrote:
      I don't quite understand why this works... but as many others have
      probably discovered if you create a namespace manager like so:
      >
      System.Xml.XmlN amespaceManager xmlNsMgr = new
      System.Xml.XmlN amespaceManager (xmlReader.Name Table);
      xmlNsMgr.AddNam espace("q", "urn:thing-schema-v1");
      >
      ....then use a query such as "/q:thing/*" then everything in the code
      below works. Why is this?
      >
      On Dec 2, 11:17 pm, "Jason Mobarak" <jason.moba...@ gmail.comwrote:
      Hello --

      I'm attempting to get a handle on how to do xpath queries with
      System.Xml -- so far the biggest hurdle has been how to deal with a
      default namespace. If I use the test xml:

      <?xml version="1.0" encoding="utf-8" ?>
      <thing xmlns="urn:thin g-schema-v1">
      <foo>foo thing</foo>
      <bar>bar thing</bar>
      <baz>baz thing</baz>
      </thing>

      ...everything in the code below fails (as in no nodes are located, when
      3 should be). However, if I remove the xmlns declaration from the
      <thingroot element everything works fine. What am I doing wrong?

      using System;
      using System.Collecti ons.Generic;
      using System.Text;

      namespace XmlTest
      {
      class Program
      {
      static void Main(string[] args)
      {
      const string szXPath = "/thing/*";
      const string szFilename = @"..\..\test-wo-xmlns.xml";

      System.Xml.XmlR eader xmlReader = new
      System.Xml.XmlT extReader(Syste m.IO.File.OpenR ead(szFilename) );

      System.Xml.XmlN amespaceManager xmlNsMgr = new
      System.Xml.XmlN amespaceManager (xmlReader.Name Table);
      xmlNsMgr.AddNam espace(String.E mpty, "urn:thing-schema-v1");

      System.Xml.XPat h.XPathDocument xpath = new
      System.Xml.XPat h.XPathDocument (xmlReader);

      System.Xml.XPat h.XPathNavigato r xpathNavi =
      xpath.CreateNav igator();

      System.Xml.XPat h.XPathNodeIter ator xpathQuery =
      xpathNavi.Selec t(szXPath);
      while(xpathQuer y.MoveNext())
      {
      string szValue = xpathQuery.Curr ent.Value;
      System.Console. WriteLine(szVal ue);
      }

      System.Xml.XPat h.XPathExpressi on xpathExpr =
      xpathNavi.Compi le(szXPath);
      xpathExpr.SetCo ntext(xmlNsMgr) ;

      xpathQuery = xpathNavi.Selec t(xpathExpr);
      while (xpathQuery.Mov eNext())
      {
      string szValue = xpathQuery.Curr ent.Value;
      System.Console. WriteLine(szVal ue);
      }

      System.Xml.XmlD ocument xmlDoc = new
      System.Xml.XmlD ocument();
      xmlDoc.Load(szF ilename);

      System.Xml.XmlN amespaceManager xmlNsMgr2 = new
      System.Xml.XmlN amespaceManager (xmlDoc.NameTab le);
      xmlNsMgr2.AddNa mespace(String. Empty,
      "urn:thing-schema-v1");

      System.Xml.XmlN odeList xmlNodes =
      xmlDoc.SelectNo des(szXPath);

      foreach(System. Xml.XmlNode xmlNode in xmlNodes)
      {
      string szValue = xmlNode.Value;
      System.Console. WriteLine(szVal ue);
      }
      }
      }

      }
      >
      >

      Comment

      • Jason Mobarak

        #4
        Re: Simple xpath query with default namespace

        Thanks Mark. You're explanation makes sense. I guess I was confused
        by the fact that I needed to introduce a prefix in to the my xpath
        query (a prefix that's no actually in the xml) in order for the library
        to allow me to query for something in a namespace, regardless of
        whether it's the default namespace.

        On Dec 3, 12:45 am, Mark R. Dawson
        <MarkRDaw...@di scussions.micro soft.comwrote:
        Hi Jason,
        namespaces in XML serve the same purpose as namespace in C#, they are a
        way to distinguish between two items that happen to have the same identifier.
        In XML you may have one XML definition that has a node called <Account
        BankNo="123"whi ch refers to a Bank Account and another node that is also
        called <Account Name="bob"that refers to a Video Rental account, so if both
        nodes are part of the same XML document how could you distinguish between
        them? The namespace allows that since one could be part of the namespacehttp://www.example.org/bankingand anotherhttp://www.example.org/videorental
        then when you have your XPath query you will need to tell XPath which Account
        element you mean by prefixing the name with the namespace in your query.
        Hence in your example because the node is part of a namespace you need to use
        that information in your XPath query.
        >
        Mark.
        --http://www.markdawson. org
        >
        "Jason Mobarak" wrote:
        I don't quite understand why this works... but as many others have
        probably discovered if you create a namespace manager like so:
        >
        System.Xml.XmlN amespaceManager xmlNsMgr = new
        System.Xml.XmlN amespaceManager (xmlReader.Name Table);
        xmlNsMgr.AddNam espace("q", "urn:thing-schema-v1");
        >
        ....then use a query such as "/q:thing/*" then everything in the code
        below works. Why is this?
        >
        On Dec 2, 11:17 pm, "Jason Mobarak" <jason.moba...@ gmail.comwrote:
        Hello --
        >
        I'm attempting to get a handle on how to do xpath queries with
        System.Xml -- so far the biggest hurdle has been how to deal with a
        default namespace. If I use the test xml:
        >
        <?xml version="1.0" encoding="utf-8" ?>
        <thing xmlns="urn:thin g-schema-v1">
        <foo>foo thing</foo>
        <bar>bar thing</bar>
        <baz>baz thing</baz>
        </thing>
        >
        ...everything in the code below fails (as in no nodes are located, when
        3 should be). However, if I remove the xmlns declaration from the
        <thingroot element everything works fine. What am I doing wrong?
        >
        using System;
        using System.Collecti ons.Generic;
        using System.Text;
        >
        namespace XmlTest
        {
        class Program
        {
        static void Main(string[] args)
        {
        const string szXPath = "/thing/*";
        const string szFilename = @"..\..\test-wo-xmlns.xml";
        >
        System.Xml.XmlR eader xmlReader = new
        System.Xml.XmlT extReader(Syste m.IO.File.OpenR ead(szFilename) );
        >
        System.Xml.XmlN amespaceManager xmlNsMgr = new
        System.Xml.XmlN amespaceManager (xmlReader.Name Table);
        xmlNsMgr.AddNam espace(String.E mpty, "urn:thing-schema-v1");
        >
        System.Xml.XPat h.XPathDocument xpath = new
        System.Xml.XPat h.XPathDocument (xmlReader);
        >
        System.Xml.XPat h.XPathNavigato r xpathNavi =
        xpath.CreateNav igator();
        >
        System.Xml.XPat h.XPathNodeIter ator xpathQuery =
        xpathNavi.Selec t(szXPath);
        while(xpathQuer y.MoveNext())
        {
        string szValue = xpathQuery.Curr ent.Value;
        System.Console. WriteLine(szVal ue);
        }
        >
        System.Xml.XPat h.XPathExpressi on xpathExpr =
        xpathNavi.Compi le(szXPath);
        xpathExpr.SetCo ntext(xmlNsMgr) ;
        >
        xpathQuery = xpathNavi.Selec t(xpathExpr);
        while (xpathQuery.Mov eNext())
        {
        string szValue = xpathQuery.Curr ent.Value;
        System.Console. WriteLine(szVal ue);
        }
        >
        System.Xml.XmlD ocument xmlDoc = new
        System.Xml.XmlD ocument();
        xmlDoc.Load(szF ilename);
        >
        System.Xml.XmlN amespaceManager xmlNsMgr2 = new
        System.Xml.XmlN amespaceManager (xmlDoc.NameTab le);
        xmlNsMgr2.AddNa mespace(String. Empty,
        "urn:thing-schema-v1");
        >
        System.Xml.XmlN odeList xmlNodes =
        xmlDoc.SelectNo des(szXPath);
        >
        foreach(System. Xml.XmlNode xmlNode in xmlNodes)
        {
        string szValue = xmlNode.Value;
        System.Console. WriteLine(szVal ue);
        }
        }
        }
        >
        }

        Comment

        Working...