tags:

views:

734

answers:

5

I want to find a simple element (Name) in an XML :

<ZoneContentMapping>  
 <ZoneContent> 
   <ContentId>72503</ContentId>  
   <StorefrontZoneId>Name</StorefrontZoneId>  
   <Type>ContentZone</Type>  
 </ZoneContent>
</ZoneContentMapping>

I am doing :

XmlNodeList objNode =  
objXML.SelectNodes("ZoneContentMapping/ZoneContent[ContentId='72503']/StorefrontZoneId");

my Node count is always zero, where am I going wrong ?

A: 

The XPath looks good, so does the XML. Tried it in XmlSpy and I get "Name" so it should work. However, try to add an additional slash at the beginning just in case...

XmlNodeList objNode = objXML.SelectNodes ("/ZoneContentMapping/ZoneContent[ContentId='72503']/StorefrontZoneId");

Or try SelectSingleNode instead...

Workshop Alex
A: 

Here is another way you could go about it if you'd like:

        string XmlFilePath = @"C:\blablabla"; 

        XmlDocument LoadXmlDoc = new XmlDocument();
        LoadXmlDoc.Load(XmlFilePath);

        XmlNodeList YourNodeList = LoadXmlDoc.GetElementsByTagName("StorefrontZoneId");

        LoadXmlDoc.Save(XmlFilePath);
transmogrify
A: 

I think the problem here is the context in which you are executing your query. If you load the document in the XPath engine I use here, the root context is the only node provided, ZoneContentMapping. Remember that your query:

ZoneContentMapping/...

Expands to:

child::ZoneContentMapping/...

As the default axis in XPath is child. So your query is probably looking for a child of ZoneContentMapping called ZoneContentMapping. Oops.

Try:

self::ZoneContentMapping/ZoneContent[ContentId='72503']/StorefrontZoneId

You can also prepend a / to the query, which does the search from the root of the XML document, regardless of your current context.

David Crawshaw
In normal circumstances, the default context is the _document node_ of the document, which will become root (`/`) in XPath, not the root node.
Pavel Minaev
A: 

This xpath works:

ZoneContentMapping/ZoneContent/StorefrontZoneId[preceding-sibling::ContentId='72503']

and here is a good resource:

http://www.codeguru.com/csharp/csharp/cs%5Fmisc/designtechniques/print.php/c7589%5F%5F1/

ScottE
And your XPath is semantically different from his how? Hint: the "non-working" XPath in the question does not in any way assume that "StorefrontZoneId was a child of ContentId".
Pavel Minaev
It's very different! Plus, I used his xml and applied the xpath to it, and got the value 'name' as was requested. The only thing I did different was use XmlNode as the type instead of XmlNodeList
ScottE
+3  A: 

Are namespaces involved? I had a similar problem parsing Amazon AWS results, which turned out to be that I wasn't providing an XmlNamespaceManager with AWS namespace specified.

XmlNamespaceManager mgr = new XmlNamespaceManager(m_xml.NameTable);
mgr.AddNamespace("amzn", "http://s3.amazonaws.com/doc/2006-03-01/");

XmlNodeList nodes = xmlDoc.SelectNodes("//amzn:Contents", mgr);

The namespace prefix is arbitrary, but seems to be necessary in the XPath even though no namespace prefix is used in the XML itself. I couldn't find a way to tell it to associate an empty namespace prefix with the specified namespace URL.

Tim