Selecting XML nodes w/ namespace and XElement

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Michael Bray

    #1

    Selecting XML nodes w/ namespace and XElement

    I'm playing around with XElement stuff, and I've come across a difficulty.
    The XML document that I'm reading contains an xmlns declaration on the main
    node...

    <root xmlns="http://www.me.com">
    <ANode>
    <BNode>Hello</BNode>
    <BNode>Goodby e</BNode>
    </ANode>
    </root>

    I want to be able to query this document using XPath. I can successfully
    do this with the following:

    XmlDocument doc = new XmlDocument();
    doc.LoadXml(s);
    XmlNamespaceMan ager nsm = new XmlNamespaceMan ager(doc.NameTa ble);
    nsm.AddNamespac e("t", "http://www.me.com");
    int n = doc.SelectNodes ("/t:root/t:ANode/t:BNode", nsm).Count;

    .... and I see that n = 2.

    But when I try to convert this to XElement (and who knows I may be
    WWWAAAYYY off here as I'm just starting to look at this):

    XmlReader rdr = XmlReader.Creat e(new StringReader(s) );
    XElement x = XElement.Load(r dr);
    XmlNamespaceMan ager nsm = new XmlNamespaceMan ager(rdr.NameTa ble);
    nsm.AddNamespac e("t", "http://www.me.com");
    int n = x.XPathSelectEl ements("/t:root/t:ANode/t:BNode", nsm).Count();

    .... I get n = 0.


    What am I doing wrong?

    -mdb

  • Anthony Jones

    #2
    Re: Selecting XML nodes w/ namespace and XElement

    "Michael Bray" <mbray@dontemai lme.comwrote in message
    news:Xns9AD6925 88F7D4mdb@207.4 6.248.16...
    I'm playing around with XElement stuff, and I've come across a difficulty.
    The XML document that I'm reading contains an xmlns declaration on the
    main
    node...
    >
    <root xmlns="http://www.me.com">
    <ANode>
    <BNode>Hello</BNode>
    <BNode>Goodby e</BNode>
    </ANode>
    </root>
    >
    I want to be able to query this document using XPath. I can successfully
    do this with the following:
    >
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(s);
    XmlNamespaceMan ager nsm = new XmlNamespaceMan ager(doc.NameTa ble);
    nsm.AddNamespac e("t", "http://www.me.com");
    int n = doc.SelectNodes ("/t:root/t:ANode/t:BNode", nsm).Count;
    >
    ... and I see that n = 2.
    >
    But when I try to convert this to XElement (and who knows I may be
    WWWAAAYYY off here as I'm just starting to look at this):
    >
    XmlReader rdr = XmlReader.Creat e(new StringReader(s) );
    XElement x = XElement.Load(r dr);
    XmlNamespaceMan ager nsm = new XmlNamespaceMan ager(rdr.NameTa ble);
    nsm.AddNamespac e("t", "http://www.me.com");
    int n = x.XPathSelectEl ements("/t:root/t:ANode/t:BNode", nsm).Count();
    >
    ... I get n = 0.
    >
    >
    What am I doing wrong?
    I've not done much with this new XElement either but I'd be willing to guess
    that since x is root and in this case is the top most node (in the
    XmlDocument the document is the top most node and root is a child). then
    the path is wrong. / refers to root and root doesn't have a child called
    root.

    Try:-

    "t:ANode/t:BNode"

    I'm currently on a my 2000 machine so I can't test that at the moment.

    --
    Anthony Jones - MVP ASP/ASP.NET


    Comment

    • Chakravarthy

      #3
      Re: Selecting XML nodes w/ namespace and XElement

      Dude,

      First, understand the difference between XMLDocument and XMLReader.
      XMLDocument is inmemory .. where are XMLReader is not a cache.

      thus, when you first queried you got the count, where are when you did the
      second mechanism, it doesn't have loaded the entire XML into memory.

      Hope am clear to you,




      "Michael Bray" <mbray@dontemai lme.comwrote in message
      news:Xns9AD6925 88F7D4mdb@207.4 6.248.16...
      I'm playing around with XElement stuff, and I've come across a difficulty.
      The XML document that I'm reading contains an xmlns declaration on the
      main
      node...
      >
      <root xmlns="http://www.me.com">
      <ANode>
      <BNode>Hello</BNode>
      <BNode>Goodby e</BNode>
      </ANode>
      </root>
      >
      I want to be able to query this document using XPath. I can successfully
      do this with the following:
      >
      XmlDocument doc = new XmlDocument();
      doc.LoadXml(s);
      XmlNamespaceMan ager nsm = new XmlNamespaceMan ager(doc.NameTa ble);
      nsm.AddNamespac e("t", "http://www.me.com");
      int n = doc.SelectNodes ("/t:root/t:ANode/t:BNode", nsm).Count;
      >
      ... and I see that n = 2.
      >
      But when I try to convert this to XElement (and who knows I may be
      WWWAAAYYY off here as I'm just starting to look at this):
      >
      XmlReader rdr = XmlReader.Creat e(new StringReader(s) );
      XElement x = XElement.Load(r dr);
      XmlNamespaceMan ager nsm = new XmlNamespaceMan ager(rdr.NameTa ble);
      nsm.AddNamespac e("t", "http://www.me.com");
      int n = x.XPathSelectEl ements("/t:root/t:ANode/t:BNode", nsm).Count();
      >
      ... I get n = 0.
      >
      >
      What am I doing wrong?
      >
      -mdb
      >

      Comment

      • Jon Skeet [C# MVP]

        #4
        Re: Selecting XML nodes w/ namespace and XElement

        On Jul 10, 12:24 pm, "Chakravart hy" <dskch...@msn.c omwrote:
        First, understand the difference between XMLDocument and XMLReader.
        XMLDocument is inmemory .. where are XMLReader is not a cache.
        >
        thus, when you first queried you got the count, where are when you did the
        second mechanism, it doesn't have loaded the entire XML into memory.
        Doesn't XElement.Load(r dr) load the whole thing into memory though?
        That's certainly what I'd expect.

        Jon

        Comment

        • Pavel Minaev

          #5
          Re: Selecting XML nodes w/ namespace and XElement

          On Jul 10, 12:45 am, "Anthony Jones" <A...@yadayaday ada.comwrote:
          "Michael Bray" <mb...@dontemai lme.comwrote in message
          >
          news:Xns9AD6925 88F7D4mdb@207.4 6.248.16...
          >
          >
          >
          >
          >
          I'm playing around with XElement stuff, and I've come across a difficulty.
          The XML document that I'm reading contains an xmlns declaration on the
          main
          node...
          >
          <root xmlns="http://www.me.com">
             <ANode>
                <BNode>Hello</BNode>
                <BNode>Goodby e</BNode>
             </ANode>
          </root>
          >
          I want to be able to query this document using XPath.  I can successfully
          do this with the following:
          >
          XmlDocument doc = new XmlDocument();
          doc.LoadXml(s);
          XmlNamespaceMan ager nsm = new XmlNamespaceMan ager(doc.NameTa ble);
          nsm.AddNamespac e("t", "http://www.me.com");
          int n = doc.SelectNodes ("/t:root/t:ANode/t:BNode", nsm).Count;
          >
          ...  and I see that n = 2.
          >
          But when I try to convert this to XElement (and who knows I may be
          WWWAAAYYY off here as I'm just starting to look at this):
          >
          XmlReader rdr = XmlReader.Creat e(new StringReader(s) );
          XElement x = XElement.Load(r dr);
          XmlNamespaceMan ager nsm = new XmlNamespaceMan ager(rdr.NameTa ble);
          nsm.AddNamespac e("t", "http://www.me.com");
          int n = x.XPathSelectEl ements("/t:root/t:ANode/t:BNode", nsm).Count();
          >
          ...  I get n = 0.
          >
          What am I doing wrong?
          >
          I've not done much with this new XElement either but I'd be willing to guess
          that since x is root and in this case is the top most node (in the
          XmlDocument the document is the top most node and root is a child).  then
          the path is wrong.  / refers to root and root doesn't have a child called
          root.
          >
           Try:-
          >
          "t:ANode/t:BNode"
          Yes, this is correct - "/" refers to the root node in the XML tree,
          which is document in XmlDocument, but <rootelement in this case.
          You may either follow the suggestion above, or load the XML into
          System.Xml.Linq .XDocument instead - then you'll get the usual
          behavior.

          By the way, why XPath? The whole point of the new APIs is to use LINQ
          queries instead:

          XNamespace t = "http://www.me.com";
          var result = doc.Elements(t + "ANode").Elemen ts(t + "BNode");

          Comment

          • Michael Bray

            #6
            Re: Selecting XML nodes w/ namespace and XElement

            Pavel Minaev <int19h@gmail.c omwrote in news:ec4a9b96-77b8-4035-bbe3-
            ac19e079ee34@k1 3g2000hse.googl egroups.com:
            Yes, this is correct - "/" refers to the root node in the XML tree,
            which is document in XmlDocument, but <rootelement in this case.
            You may either follow the suggestion above, or load the XML into
            System.Xml.Linq .XDocument instead - then you'll get the usual
            behavior.
            >
            By the way, why XPath? The whole point of the new APIs is to use LINQ
            queries instead:
            >
            XNamespace t = "http://www.me.com";
            var result = doc.Elements(t + "ANode").Elemen ts(t + "BNode");
            >
            I'm using XPath because I want to be able to specify in a configuration
            file which set of nodes to analyze. What you say makes a lot of sense if I
            always know the path and can hard code it.

            Even so, testing your code yields no results:

            string s = "<root xmlns='http://www.me.com'><AN ode><BNode>Hell o</BNode>
            <BNode>Goodby e</BNode></ANode></root>";

            XDocument doc = XDocument.Parse (s);
            XNamespace ns = "http://www.me.com";
            int nn = doc.Elements(ns + "ANode").Elemen ts(ns + "BNode").Count( );

            yields.. nn = 0. did I miss something?

            -mdb

            Comment

            • Michael Bray

              #7
              Re: Selecting XML nodes w/ namespace and XElement

              "Anthony Jones" <Ant@yadayadaya da.comwrote in
              news:###1CTg4IH A.1192@TK2MSFTN GP05.phx.gbl:
              I've not done much with this new XElement either but I'd be willing to
              guess that since x is root and in this case is the top most node (in
              the XmlDocument the document is the top most node and root is a
              child). then the path is wrong. / refers to root and root doesn't
              have a child called root.
              >
              Try:-
              >
              "t:ANode/t:BNode"
              Yup tried that before I posted (along with every other path I could think
              of).. Same result - 0 nodes selected.

              I'm just grasping at straws at this point - almost ready to abandon XML
              Linq for now and stick with what works.

              -mdb

              Comment

              • Martin Honnen

                #8
                Re: Selecting XML nodes w/ namespace and XElement

                Michael Bray wrote:
                Even so, testing your code yields no results:
                >
                string s = "<root xmlns='http://www.me.com'><AN ode><BNode>Hell o</BNode>
                <BNode>Goodby e</BNode></ANode></root>";
                >
                XDocument doc = XDocument.Parse (s);
                XNamespace ns = "http://www.me.com";
                int nn = doc.Elements(ns + "ANode").Elemen ts(ns + "BNode").Count( );
                >
                yields.. nn = 0. did I miss something?
                Yes, certainly, the XDocument doc you construct has a root element named
                'root' that your code ignores. You need/want
                doc.Root.Elemen ts(ns + "ANode").Elemen ts(ns + "BNode").Count( )
                or (naming the root explicitly)
                doc.Element(ns + "root").Element s(ns + "ANode").Elemen ts(ns +
                "BNode").Count( )

                --

                Martin Honnen --- MVP XML
                http://JavaScript.FAQTs.com/

                Comment

                • Martin Honnen

                  #9
                  Re: Selecting XML nodes w/ namespace and XElement

                  Michael Bray wrote:
                  "Anthony Jones" <Ant@yadayadaya da.comwrote in
                  news:###1CTg4IH A.1192@TK2MSFTN GP05.phx.gbl:
                  >
                  >I've not done much with this new XElement either but I'd be willing to
                  >guess that since x is root and in this case is the top most node (in
                  >the XmlDocument the document is the top most node and root is a
                  >child). then the path is wrong. / refers to root and root doesn't
                  >have a child called root.
                  >>
                  > Try:-
                  >>
                  >"t:ANode/t:BNode"
                  >
                  Yup tried that before I posted (along with every other path I could think
                  of).. Same result - 0 nodes selected.
                  Here is a working sample that outputs 2:

                  XElement root = XElement.Load(@ "..\..\XMLFile1 .xml");
                  XmlNamespaceMan ager mgr = new XmlNamespaceMan ager(new
                  NameTable());
                  mgr.AddNamespac e("pf", "http://www.me.com");

                  Console.WriteLi ne(root.XPathSe lectElements("p f:ANode/pf:BNode",
                  mgr).Count());

                  XML document is

                  <?xml version="1.0" encoding="utf-8" ?>
                  <root xmlns="http://www.me.com">
                  <ANode>
                  <BNode>Hello</BNode>
                  <BNode>Goodby e</BNode>
                  </ANode>
                  </root>

                  If your code does not find anything then please show us a complete
                  sample that demonstrates that, somewhere there must be a mistake.



                  --

                  Martin Honnen --- MVP XML
                  http://JavaScript.FAQTs.com/

                  Comment

                  • Michael Bray

                    #10
                    Re: Selecting XML nodes w/ namespace and XElement - RESOLVED

                    "Anthony Jones" <Ant@yadayadaya da.comwrote in
                    news:###1CTg4IH A.1192@TK2MSFTN GP05.phx.gbl:
                    I've not done much with this new XElement either but I'd be willing to
                    guess that since x is root and in this case is the top most node (in
                    the XmlDocument the document is the top most node and root is a
                    child). then the path is wrong. / refers to root and root doesn't
                    have a child called root.
                    >
                    Try:-
                    >
                    "t:ANode/t:BNode"

                    OK hmmm.. as I was playing around I think I fixed it... I can query
                    using both the XPath query mode and the Elements(..)... Here's the code
                    that works for me:

                    string s = "<root xmlns='http://www.me.com'><AN ode><BNode>Hell o</BNode>
                    <BNode>Goodby e</BNode></ANode></root>";

                    XmlReader rdr = XmlReader.Creat e(new StringReader(s) );
                    XDocument doc = XDocument.Load( rdr);
                    XmlNamespaceMan ager nsm = new XmlNamespaceMan ager(rdr.NameTa ble);
                    nsm.AddNamespac e("t", "http://www.me.com");
                    XNamespace ns = "http://www.me.com";

                    int n = doc.XPathSelect Elements("/t:root/t:ANode/t:BNode", nsm).Count();
                    int nn = doc.Elements(ns + "root").Element s(ns + "ANode").Elemen ts(ns +
                    "BNode").Count( );
                    int nnn = doc.Elements("r oot").Elements( "ANode").Elemen ts("BNode").Cou nt();

                    var q = doc.XPathSelect Elements("/t:root/t:ANode/t:BNode", nsm);
                    foreach (var v in q) Console.WriteLi ne(v.Value);


                    yields.... n = 2 nn = 2 nnn = 0
                    and outputs: Hello Goodbye

                    so I think the main thing that fixed it was loading into XDocument instead
                    of XElement. Also, when querying using the Elements() I needed to make
                    sure I added the XNamespace.

                    Thanks to everyone for their input... I knew it would be something simple
                    I was missing.

                    -mdb

                    Comment

                    • Michael Bray

                      #11
                      Re: Selecting XML nodes w/ namespace and XElement

                      Martin Honnen <mahotrash@yaho o.dewrote in news:#3LFOoq4IH A.4340
                      @TK2MSFTNGP06.p hx.gbl:
                      Yes, certainly, the XDocument doc you construct has a root element named
                      'root' that your code ignores. You need/want
                      doc.Root.Elemen ts(ns + "ANode").Elemen ts(ns + "BNode").Count( )
                      or (naming the root explicitly)
                      doc.Element(ns + "root").Element s(ns + "ANode").Elemen ts(ns +
                      "BNode").Count( )
                      Haha yeah I actually just meandered into the same solution and posted the
                      same answer... Turned out that my original problem was that I was loading
                      into XElement instead of XDocument!

                      Thanks for you help!!

                      -mdb

                      Comment

                      • Michael Bray

                        #12
                        Re: Selecting XML nodes w/ namespace and XElement

                        Martin Honnen <mahotrash@yaho o.dewrote in news:uTBS$pq4IH A.4340
                        @TK2MSFTNGP06.p hx.gbl:
                        If your code does not find anything then please show us a complete
                        sample that demonstrates that, somewhere there must be a mistake.
                        Hmmm now that is odd... I confirm that this works, but I can't see any
                        significant difference from what (I thought) I tested... maybe I just
                        was too blinded by frustration and was making silly mistakes.

                        Oh well... I have things working like I need them now, so I'm happy again.
                        Thanks!

                        -mdb

                        Comment

                        Working...