XPath is (deliberately) not designed for for the case where you want to use the same XPath expression for some unknown namespaces that only live in the XML document. You are expected to know the namespace ahead of time, declare the namespace to the XPath processor, and use the name in your expression. The answers by Martin and Dan show how to do this in C#.
The reason for this difficulty is best expressed in the XML namespaces spec:
We envision applications of Extensible Markup Language (XML) where a single XML document may contain elements and attributes (here referred to as a "markup vocabulary") that are defined for and used by multiple software modules. One motivation for this is modularity: if such a markup vocabulary exists which is well-understood and for which there is useful software available, it is better to re-use this markup rather than re-invent it.
Such documents, containing multiple markup vocabularies, pose problems of recognition and collision. Software modules need to be able to recognize the elements and attributes which they are designed to process, even in the face of "collisions" occurring when markup intended for some other software package uses the same element name or attribute name.
These considerations require that document constructs should have names constructed so as to avoid clashes between names from different markup vocabularies. This specification describes a mechanism, XML namespaces, which accomplishes this by assigning expanded names to elements and attributes.
That is, namespaces are supposed to be used to make sure you know what your document is talking about: is that <head>
element talking about the preamble to an XHTML document or somebodies head in an AnatomyML document? You are never "supposed" to be agnostic about the namespace and it's pretty much the first thing you ought to define in any XML vocabulary.
It should be possible to do what you want, but I don't think it can be done in a single XPath expression. First of all you need to rummage around in the document and extract all the namespaceURIs, then add these to the namespace manager and then run the actual XPath expression you want (and you need to know something about the distribution of namespaces in the document at this point, or you have a lot of expressions to run). I think you are probably best using something other than XPath (e.g. a DOM or SAX-like API) to find the namespaceURIs, but you could also explore the XPath namespace-axis (in XPath 1.0), use the namespace-uri-from-QName
function (in XPath 2.0) or use expressions like Oleg's "configuration/*[local-name() = 'MyNode']"
. Anyway, I think your best bet is to try and avoid writing namespace agnostic XPath! Why do you not know your namespace ahead of time? How are you going to avoid matching things you don't intend to match?
Edit - you know the namespaceURI?
So it turns out that your question confused us all. Apparently you know the namespace URI, but you don't know the namespace prefix that's used in the XML document. Indeed, in this case no namespace prefix is used and the URI becomes the default namspace where it is defined. The key thing to know is that the chosen prefix (or lack of a prefix) is irrelevant to your XPath expression (and XML parsing in general). The prefix / xmlns attribute is just one way to associate a node with a namespace URI when the document is expressed as text. You may want to take a look at this answer, where I try and clarify namespace prefixes.
You should try to think of the XML document in the same way the parser thinks of it - each node has a namespace URI and a local name. The namespace prefix / inheritance rules just saves typing the URI out lots of times. One way to write this down is in Clark notation: that is, you write {http://www.example.com/namespace/example}LocalNodeName, but this notation is usually just used for documentation - XPath knows nothing about this notation.
Instead, XPath uses its own namespace prefixes.Something like /ns1:root/ns2:node
. But these are completely separate from and nothing to do with any prefixes that may be used in the original XML document. Any XPath implementation will have a way to map it's own prefixes with namespace URIs. For the C# implementation you use an XmlNamespaceManager
, in Perl you provide a hash, xmllint takes command line arguments... So all you need to do is create some arbitrary prefix for the namespace URI you know, and use this prefix in the XPath expression. It doesn't matter what prefix you use, in XML you just care about the combination of the URI and the localName.
The other thing to remember (it's often a surprise) is that XPath doesn't do namespace inheritance. You need to add a prefix for every that has a namespace, irrespective of whether the namespace comes from inheritance, an xmlns attribute, or a namespace prefix. Also, although you should always think in terms of URIs and localNames, there are also ways to access the prefix from an XML document. It's rare to have to use these.