简体   繁体   中英

How to get list of values when XML contains many namespaces

I have following XML:

<?xml version="1.0" encoding="utf-16"?>
<cincinnati xmlns="http://www.sesame-street.com/abc/def/1">
  <cincinnatiChild xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <ElementValue xmlns:a="http://schemas.data.org/2004/07/sesame-street.abc.def.ghi">
      <a:someField>false</a:someField>
      <a:data xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <b:KeyValueThing>
          <b:Key>key1</b:Key>
          <b:Value i:type="a:ArrayOfPeople">
            <a:Person>
              <a:firstField>
              </a:firstField>
              <a:dictionary>
                <b:KeyValueThing>
                  <b:Key>ID</b:Key>
                  <b:Value i:type="c:long" xmlns:c="http://www.w3.org/2001/XMLSchema">000101</b:Value>
                </b:KeyValueThing>
                <b:KeyValueThing>
                  <b:Key>Name</b:Key>
                  <b:Value i:type="c:string" xmlns:c="http://www.w3.org/2001/XMLSchema">John</b:Value>
                </b:KeyValueThing>
              </a:dictionary>
            </a:Person>
            <a:Person>
            ...
                  <b:Value i:type="c:long" xmlns:c="http://www.w3.org/2001/XMLSchema">000102</b:Value>
            ...
            </a:Person>
          </b:Value>
        </b:KeyValueThing>
      </a:data>
    </ElementValue>
  </cincinnatiChild>
</cincinnati>

I need to get a list if ID values, eg 000101, 000102... .

I think using XPath makes sense here but the multitude of namespaces makes it confusing (so a simple XmlNamespaceManager won't do).

Basically I need something like this (this syntax is of course not correct):

XmlDocument doc = // Load the xml
doc.DocumentElement.SelectSingleNode("/cincinati/cincinnatiChild/ElementValue/a:data/b:KeyValueThing/b:Value/a:Person/a:dictionary[b:KeyValueThing/b:Key='ID']");

also when I do doc.DocumentElement.SelectSingleNode("/cincinnati") or doc.DocumentElement.SelectSingleNode("/cincinnatiChild") I get null .

Since I'm unsure how to piece together al the helpfull advice from the comments I would like to see a working c# code line, either XmlDocument or XDocument are OK.

I also tries this before the SelectSingleNode :

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("a", "http://schemas.data.org/2004/07/sesame-street.abc.def.ghi");
nsmgr.AddNamespace("b", "http://schemas.microsoft.com/2003/10/Serialization/Arrays");
nsmgr.AddNamespace("c", "http://www.w3.org/2001/XMLSchema");
nsmgr.AddNamespace("i", "http://www.w3.org/2001/XMLSchema-instance");
nsmgr.AddNamespace("d", "http://www.sesame-street.com/abc/def/1");

You could bypass the namespace issues using the local-name()-function.

ie: in stead of b:KeyValueThing use *[local-name()='KeyValueThing']

a simple global XPath could look like this:

//*[local-name()='KeyValueThing'][*[local-name()='Key' and text()='ID' ]]/*[local-name()='Value']/text()

If you want to be more precise and speed up the XPath it would look like this:

/*[local-name()='cincinnati']/*[local-name()='cincinnatiChild']/*[local-name()='ElementValue']/*[local-name()='data']/*[local-name()='KeyValueThing']/*[local-name()='Value']/*[local-name()='Person']/*[local-name()='dictionary']/*[local-name()='KeyValueThing'][*[local-name()='Key' and text()='ID' ]]/*[local-name()='Value']/text()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM