472,145 Members | 1,578 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,145 software developers and data experts.

XmlDocument.SelectSingleNode XPathException

Hi;

I am calling SelectSingleNode("/xml/s:Schema/s:ElementType/@name") where
"/xml/s:Schema/s:ElementType/@name is a legit xpath statement (xml is the
name of the rootnode) and that xpath statement works fine on the document in
XmlSpy.

However, when I call this is .NET 1.1, I get the following exception:

XPathException {"Namespace Manager or XsltContext needed. This query has a
prefix, variable, or user-defined function."}

Any ideas?
--
thanks - dave
Nov 12 '05 #1
6 7682
Hi Dave,

Welcome to MSDN newsgroup.
As for the XPathException you encountered, it is caused by the namespace
prefix in the xpath didn't has a namespace URI mapped. In .net , when we
call xpath selection API and the xpath expression contains namespace
prefix, we need to attach an XmlNamespaceManager which contains the
namespace mapping (prefix <---> actual URI). The following MSDN reference
have mentioned using XmlNamespaceManager in both XmlNode.SelectSingleNode
or through XPathNavigator:

#XPath Queries with Namespaced Mapped Prefixes
http://msdn.microsoft.com/library/en...hquerieswithna
mespacedmappedprefixes.asp?frame=true

#XmlNode.SelectSingleNode Method
http://msdn.microsoft.com/library/en...XmlXmlNodeClas
sSelectSingleNodeTopic.asp?frame=true

Hope helps. Thanks,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)

Nov 12 '05 #2
Hi;

Since I don't know the namespaces beforehand I need to read them from the
xml file. Is there any way to tell .NET to read them itself (they are in the
file)? If not, is there a method call to get the set of defined namespaces so
I can then set them?

thanks - dave
"Steven Cheng[MSFT]" wrote:
Hi Dave,

Welcome to MSDN newsgroup.
As for the XPathException you encountered, it is caused by the namespace
prefix in the xpath didn't has a namespace URI mapped. In .net , when we
call xpath selection API and the xpath expression contains namespace
prefix, we need to attach an XmlNamespaceManager which contains the
namespace mapping (prefix <---> actual URI). The following MSDN reference
have mentioned using XmlNamespaceManager in both XmlNode.SelectSingleNode
or through XPathNavigator:

#XPath Queries with Namespaced Mapped Prefixes
http://msdn.microsoft.com/library/en...hquerieswithna
mespacedmappedprefixes.asp?frame=true

#XmlNode.SelectSingleNode Method
http://msdn.microsoft.com/library/en...XmlXmlNodeClas
sSelectSingleNodeTopic.asp?frame=true

Hope helps. Thanks,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)

Nov 12 '05 #3

Thanks for your reply Dave,

As far as I known, the XmlDocument or XmlNode hasn't as certain method to
retrieve all the namepace/prefix pairs in itself or sub nodes. Generally if
the xpath is passed from other components, they should also provide the
namespace/prefix pair which are necessary. If you want to programmaticaly
retreive all the namespace/prefix pairs in a XmlDocument( in memory or from
file). We can use XmlTextReader to loop through all the nodes in the xml
document and retrieve all the namespaces/prefix pairs in xml document like;

XmlTextReader reader = new XmlTextReader(@"..\..\data.xml");

XmlNamespaceManager nsmanager = new XmlNamespaceManager(doc.NameTable);

while (reader.Read())
{
nsmanager.AddNamespace(reader.Prefix, reader.NamespaceURI);
}

reader.Close();

Then, we can loop through all the namepspace through:

foreach (String prefix in nsmanager)
{
Console.WriteLine("Prefix={0}, Namespace={1}",
prefix,nsmgr.LookupNamespace(prefix));
}
However, this nsmanager can be used only for those full qualified element
in xpath. For example, if a xmldocument has a default namespace, we need to
explicitly specify an prefix for it in XmlNamespaceManger rather than add
it as default namespace:

=============================
<root xmlns="http://www.test.org"
xmlns:sns="http://www.test.org/sub"
xmlns:mns="http://www.test.org/mini">
<data>
<items>
<item id="1">
<sns:subItem sid="11">

</sns:subItem>
<sns:subItem sid="12">

</sns:subItem>
</item>
<item id="2">
<sns:subItem sid="21">

</sns:subItem>
</item>
</items>
</data>
</root>
======================================

XmlNamespaceManager mgr = new XmlNamespaceManager(new NameTable());
mgr.AddNamespace("tns", "http://www.test.org");
mgr.AddNamespace("sns","http://www.test.org/sub");

XmlDocument doc = new XmlDocument();

doc.Load(@"..\..\data.xml");
string xpath = "//tns:data/tns:items/tns:item/sns:subItem";
XmlNode node = doc.SelectSingleNode(xpath,mgr);

Console.WriteLine("{0}", node==null);

#Use mgr.AddNamespace(string.Empty,"http://www.test.org")
and xpath = "//data/items/item/sns:subItem" will not work.
HTH. Thanks,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)

Nov 12 '05 #4
Yuck.

Our situation is users will pass an xml file to our application so we have
no way of knowing what namespaces they are using. And it would be really bad
if we asked them to type in namespaces that are in the file. So I guess we'll
have to parse.

It's strange that .NET requires that the namespaces be set when they exist
in the xml itself. I work in java too and every java library that implements
xpath reads the namespaces itself from the xml.

Are you sure .NET has this limitation?

thanks - dave

"Steven Cheng[MSFT]" wrote:

Thanks for your reply Dave,

As far as I known, the XmlDocument or XmlNode hasn't as certain method to
retrieve all the namepace/prefix pairs in itself or sub nodes. Generally if
the xpath is passed from other components, they should also provide the
namespace/prefix pair which are necessary. If you want to programmaticaly
retreive all the namespace/prefix pairs in a XmlDocument( in memory or from
file). We can use XmlTextReader to loop through all the nodes in the xml
document and retrieve all the namespaces/prefix pairs in xml document like;

XmlTextReader reader = new XmlTextReader(@"..\..\data.xml");

XmlNamespaceManager nsmanager = new XmlNamespaceManager(doc.NameTable);

while (reader.Read())
{
nsmanager.AddNamespace(reader.Prefix, reader.NamespaceURI);
}

reader.Close();

Then, we can loop through all the namepspace through:

foreach (String prefix in nsmanager)
{
Console.WriteLine("Prefix={0}, Namespace={1}",
prefix,nsmgr.LookupNamespace(prefix));
}
However, this nsmanager can be used only for those full qualified element
in xpath. For example, if a xmldocument has a default namespace, we need to
explicitly specify an prefix for it in XmlNamespaceManger rather than add
it as default namespace:

=============================
<root xmlns="http://www.test.org"
xmlns:sns="http://www.test.org/sub"
xmlns:mns="http://www.test.org/mini">
<data>
<items>
<item id="1">
<sns:subItem sid="11">

</sns:subItem>
<sns:subItem sid="12">

</sns:subItem>
</item>
<item id="2">
<sns:subItem sid="21">

</sns:subItem>
</item>
</items>
</data>
</root>
======================================

XmlNamespaceManager mgr = new XmlNamespaceManager(new NameTable());
mgr.AddNamespace("tns", "http://www.test.org");
mgr.AddNamespace("sns","http://www.test.org/sub");

XmlDocument doc = new XmlDocument();

doc.Load(@"..\..\data.xml");
string xpath = "//tns:data/tns:items/tns:item/sns:subItem";
XmlNode node = doc.SelectSingleNode(xpath,mgr);

Console.WriteLine("{0}", node==null);

#Use mgr.AddNamespace(string.Empty,"http://www.test.org")
and xpath = "//data/items/item/sns:subItem" will not work.
HTH. Thanks,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)

Nov 12 '05 #5
Hi Dave,

Thanks for your followup.
As for using XmlNamespaceManager to help executing XPATH in xmldocument
which contains namespace/prefix, I don't think it's the limitation of
net's XML interfaces. I'm sure this is a quite reasonable feature, here is
the reason why the XmlNamespaceManager is necessary:

When there is namespace in an xml document to scope elements in different
area(schemas), we use prefixs to identify namespaceURI. Like:

===============================
<?xml version="1.0" encoding="utf-8" ?>
<root xmlns="http://www.test.org"
xmlns:sns="http://www.test.org/sub">
<data>
<items>
<item id="1">
<sns:subItem sid="11">

</sns:subItem>
<sns:subItem sid="12">

</sns:subItem>
</item>
</items>
</data>
</root>
==============================

when we need to quer the <sns:subItem sid="11">

maybe we'll think that use the following xpath is quite normal:

//sns:subItem[@sid="11"]

However, according to the W3C XPATH1.0 specification. The full qualified
name of an element is actually it's namespaceURI(not prefix) combined with
its localname, that means the above path should be:

//http://www.test.org/sub:subItem[@sid="11"]

And as we known, namespace prefix is just a alias of namespaceURI, which
can be replaced by any other one as long as it can uniquely identity that
namespaceURI in the document. So .net framework provide the
XmlNamespaceManager which can help specify Namespace with arbitary prefix
value. For example, the above selection can be replaced by

XmlNamespaceManager mgr = new XmlNamespaceManager(new NameTable());

mgr.AddNamespace("aaa","http://www.test.org/sub");

string xpath = "//aaa:subItem[@sid='11']";

"sns" is just an alias, the actual idenitfy is "http://www.test.org/sub",
and the prefix in xpath should be able to be replaced by another alias.
(not only limited to "sns")

I'm not sure if those JAVA xml api is capable of this. However, at least I
think using prefix directly in xpath without any mapping info between
prefix---namespaceURI is not a reasonable behavior. Also, some times we're
not executing Xpath on a whole XmlDocument, just on a XmlNode , then where
does the API to look for the namespace /prefix declaration on the fly?
That's also why the .net using the XmlNamespaceManager to specify the
prefix---namespaceURI mapping.

#HOW TO: Specify Namespaces When You Use an XmlDocument to Execute XPath
Queries in Visual C# .NET
http://support.microsoft.com/default...b;en-us;318545

If you still have anything unclear, please feel free to post here. Thanks,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)


Nov 12 '05 #6
Thanks for your reply Dave,

As you said:
===========
The "xmlns:sns="http://www.test.org/sub">" in the xml itself provides the
necessary information to turn:
//sns:subItem[@sid="11"]
into:
//http://www.test.org/sub:subItem[@sid="11"]
===========

yes, the XML Node or fragment did include the namespace declaraion.
However, this doesn't means that our XPATH can only use "sns" to idenity
the "http://www.test.org/sub" namespace. The "sns" is only an alias. So
the following two xml fragment should be identical (validate through schema)

#fragment A
<root xmlns:sns="http://www.test.org/sub">
<sns:item>
.......
</sns:item>
</root>

#fragment B
<root xmlns:aaa="http://www.test.org/sub">
<aaa:item>
.......
</aaa:item>
</root>

However, if we only use the

"//sns:item" xpath and haven't specify an prefix/ URI mapping, it
will only work( using the JAVA API you mentioned) in

fragment A , but not in fragment B( though framgment A is exactly the same
xml document as fragment B).

And when using .net's Xpath selection, since we specify the
XmlNamespaceManager which provide the prefix(in our xpath) ----
namespaceURI mapping , we can perform the xpath selection no matter the
namespace prefix is changed to anyone in the source xml document. Also,
the prefix in our XPATH can vary , such as :

//bbb:item using AddNamespace("bbb", "http://test.org/sub")

//ccc:item using AddNamespace("ccc", "http://test.org/sub")

Anyway, I think the prefix( in xpath ) is not simply an alias( it should
always has a namespaceURI mapped to it) , otherwise, the prefix will be
meaningless alone.

Just some of my understanding. Thanks,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)



Nov 12 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Jesper Stocholm | last post: by
5 posts views Thread by Gnic | last post: by
reply views Thread by Ewan Fairweather | last post: by
5 posts views Thread by Alan Silver | last post: by
1 post views Thread by =?Utf-8?B?RGF2aWRHQg==?= | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.