I have an xml with various namespaces that i would like to query using .SelectNodes(string xPath)
The problem that i notice is that the xPath query return nothing as long as i have all those namespaces around.
is there anyway to tell XmlDocument.SelectNodes to ignore those namespaces and just get me the correct elements (the elements that i query doesn't seem to have namespaces prefix)?
if there is, can anyone please provide me an example of how to do it? what should i defined before/when i query the nodes?
Thanks for the help.
Correction: i still can't figure what the problem is. here is my xml:
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:gf="http://schemas.google.com/finance/2007"
xmlns:gd="http://schemas.google.com/g/2005" >
<id>http://finance.google.com/finance/feeds/[email protected]/portfolios</id>
<updated>2009-12-15T19:32:21.000Z</updated>
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/finance/2007#portfolio" />
<title type="text" >Portfolio Feed</title>
<link rel="alternate" type="text/html" href="http://finance.google.com/finance/portfolio?action=view" />
<link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://finance.google.com/finance/feeds/default/portfolios" />
<link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="http://finance.google.com/finance/feeds/default/portfolios" />
<link rel="self" type="application/atom+xml" href="http://finance.google.com/finance/feeds/default/portfolios" />
<openSearch:totalResults>24</openSearch:totalResults>
<openSearch:startIndex>1</openSearch:startIndex>
<openSearch:itemsPerPage>24</openSearch:itemsPerPage>
<entry>
<id>http://finance.google.com/finance/feeds/[email protected]/portfolios/2</id>
<updated>2009-12-14T16:26:53.000Z</updated>
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/finance/2007#portfolio" />
<title type="text" >Main</title>
<link rel="self" type="application/atom+xml" href="http://finance.google.com/finance/feeds/default/portfolios/2" />
<link rel="edit" type="application/atom+xml" href="http://finance.google.com/finance/feeds/default/portfolios/2" />
<gd:feedLink href="http://finance.google.com/finance/feeds/[email protected]/portfolios/2/positions" />
<gf:portfolioData currencyCode="USD" gainPercentage="0.0" return1w="0.0" return1y="0.0" return3m="0.0" return3y="0.0" return4w="0.0" return5y="0.0" returnOverall="0.0" returnYTD="0.0" />
</entry>
</feed>
and here is my code:
XmlDocument xml = ExecuteRequest(url);
var xmlnsManager = new System.Xml.XmlNamespaceManager(xml.NameTable);
xmlnsManager.AddNamespace("xmlns:openSearch", "http://a9.com/-/spec/opensearchrss/1.0/");
xmlnsManager.AddNamespace("xmlns:gf", "http://schemas.google.com/finance/2007");
xmlnsManager.AddNamespace("xmlns:gd", "http://schemas.google.com/g/2005");
var nodes = xml.SelectNodes("//feed/entry", xmlnsManager);
and my nodes count is still 0! any idea?
There is no method to connect a namespace prefix to a namespace in XPath. The hosting library can provide these services. It is strongly advised that we take advantage of those features and create namespace prefixes that may be used to qualify XML element and attribute names as needed.
XML Namespaces - The xmlns Attribute When using prefixes in XML, a namespace for the prefix must be defined. The namespace can be defined by an xmlns attribute in the start tag of an element. The namespace declaration has the following syntax. xmlns:prefix="URI".
XPath defines a way to compute a string-value for each type of node. Some types of nodes also have names. XPath fully supports XML Namespaces. Thus, the name of a node is modeled as a pair consisting of a local part and a possibly null namespace URI; this is called an expanded-name.
An XML namespace is a collection of names that can be used as element or attribute names in an XML document. The namespace qualifies element names uniquely on the Web in order to avoid conflicts between elements with the same name.
You need to create a namespace manager, setup all the namespaces that you want to use and their prefix and then in the XPath, you need to use the prefix.
var doc = new XmlDocument();
doc.Load("myfile.xml");
var xmlnsManager = new System.Xml.XmlNamespaceManager(doc.NameTable);
xmlnsManager.AddNamespace("ns", "http://example.org/schema.xsd");
doc.SelectNodes("//ns:MyElement",xmlnsManager);
Warning: I did not compile this code.
I'm not as familiar with the .NET api, but you might be able to send in a more generic XPATH that ignores namespaces by matching on any element(e.g. *
) and using the local-name
in the predicate filters.
e.g. using /*[local-name()='foo']/*[local-name()='bar']/*[local-name()='baz']
to find ns:foo/ns:bar/ns:baz
without declaring the ns namespace.
That way you don't have to bind to a particular namespace at compile time and can pass in arbritrary XPATH statements.
Obviously, by using namespace-unaware XPATH statements you could get unintended results(if there is mixed namespace content with elements of the same name) and the XPATH is really verbose.
In XPATH 2.0 you can use wildcards for namespaces: /*:foo/*:bar/*:baz
, but you would have to use Saxon to get XSLT/XPATH 2.0 support in .NET.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With