Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XPATHS and Default Namespaces

What is the story behind XPath and support for namespaces? Did XPath as a specification precede namespaces? If I have a document where elements have been given a default namespace:

<foo xmlns="uri" />

It appears as though some of the XPath processor libraries won't recognize //foo because of the namespace whereas others will. The option my team has thought about is to add a namespace prefix using regular expressions to the XPath (you can add a namespace prefix via XmlNameTable) but this seems brittle since XPath is such a flexible language when it comes to node tests.

Is there a standard that applies to this?

My approach is a bit hackish but it seems to work fine; I remove the xmlns declaration with a search/replace and then apply XPath.

string readyForXpath = Regex.Replace(xmldocument, "xmlns=\".+\"", String.Empty );

Is that a fair approach or has anyone solved this differently?

like image 896
t3rse Avatar asked Aug 14 '08 17:08

t3rse


People also ask

What is the default XML namespace?

When you use multiple namespaces in an XML document, you can define one namespace as the default namespace to create a cleaner looking document. The default namespace is declared in the root element and applies to all unqualified elements in the document. Default namespaces apply to elements only, not to attributes.

What are Xpaths used for?

XPath stands for XML Path Language. It uses a non-XML syntax to provide a flexible way of addressing (pointing to) different parts of an XML document. It can also be used to test addressed nodes within a document to determine whether they match a pattern or not.

What is the use of namespace in XSLT?

In XML a namespace is a collection of names used for elements and attributes. A URI (usually, a URL) is used to identify a particular collection of names.


2 Answers

You need local-name():

http://www.w3.org/TR/xpath#function-local-name

To crib from http://web.archive.org/web/20100810142303/http://jcooney.net:80/archive/2005/08/09/6517.aspx:

<foo xmlns='urn:foo'>
  <bar>
    <asdf/>
  </bar>            
</foo>

This expression will match the “bar” element:

  //*[local-name()='bar'] 

This one won't:

 //bar
like image 121
Stu Avatar answered Sep 27 '22 21:09

Stu


I tried something similar to what palehorse proposed and could not get it to work. Since I was getting data from a published service I couldn't change the xml. I ended up using XmlDocument and XmlNamespaceManager like so:

XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlWithBogusNamespace);            
XmlNamespaceManager nSpace = new XmlNamespaceManager(doc.NameTable);
nSpace.AddNamespace("myNs", "http://theirUri");

XmlNodeList nodes = doc.SelectNodes("//myNs:NodesIWant",nSpace);
//etc
like image 38
Andrew Cowenhoven Avatar answered Sep 27 '22 21:09

Andrew Cowenhoven