Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

XPath question 1

Status
Not open for further replies.

vvlad

Programmer
May 27, 2002
151
DE
Hi,

I've run into this accidentally, with an XML file that was incorrectly generated.

What I do is simply read the attributes of a couple of nodes in a standard way.

Code:
                XPathDocument Doc = new XPathDocument(XMLFile);
                XPathNavigator navigator = Doc.CreateNavigator();
                XmlNamespaceManager ns = new XmlNamespaceManager(navigator.NameTable);

                XPathNodeIterator iterator = navigator.Select("/xxx/yyy");

                iterator.MoveNext();
                Attr = iterator.Current.GetAttribute("zzz", ns.DefaultNamespace);

The XML file contained a wrong xmlns attribute and the code never returned anything, no error or warning but also no value for the attribute. After completely removing the xmlns attribute, everything works fine.

Could someone explain me why this happens?

Thanks

vlad
 
Let me reformulate the question.

I have to process the files even if the value of that attribute is wrong. Is there a way to do it, without having to manually remove the attribute from the files? There are a lot of them.


vlad
 
shot in the dark, but if the namespace is ignored then don't reference it. using either an XmlReader or XmlDocument object, navigate to the node(s) and cycle through the attributes.
Code:
XmlDocument doc = new XmlDocument();
doc.Load("name of file");
NodeCollection nodes = doc.SelectNodes("xpath query");
foreach(XmlNode node in nodes)
{
   foreach(XmlNode attribute in node.Attributes)
   {
      Console.WriteLine("{0}={1}", attribute.Name, attribute.Value);
   }
}

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Thank you for the answer.

I have VS 2005 so had to use XmlNodeList (class NodeCollection not found), but the result is the same. With the attribute nothing happens, when I remove it everything works fine.

vlad
 
I'm not an expert of xml by any means. I would start in forum412 to determine how to ignore namespaces. then take the concept and apply it to C#

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
The problem of the "problem" is that it is not clearly described. You go that distance in abstracting the essence of the problem with xxx, yyy, zzz but think it is better not to show a concrete extract of what you mean by all the description.
>The XML file contained a wrong xmlns attribute...
xmlns is never an attribute. It is a predefined namespace prefix. So what does it mean by it being wrong?
>Attr = iterator.Current.GetAttribute("zzz", ns.DefaultNamespace);
Do you mean attribute zzz is in the default namespace? But how come an attribute in a default namespace of the node does not need a prefix to let know? It is have no nsmespace prefix, why not let the 2nd argument being an empty string? If it is prefixed with a namespace coincide with the default namespace, how is it returning wrong with ns.DefaultNamespace or whatever. There seems nothing hardcoded there. The engine reads the wrong namespace and treat it as such. How does wrong mean? At least it is consistently wrong. What wrong with consistently wrong? You are not validating the xml against schema...
 
excellent insight tsuji.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
[tt]//etc etc
iterator.MoveNext();
[red]//[/red]Attr = iterator.Current.GetAttribute("zzz", ns.DefaultNamespace);
[blue]
bool b;
bool bfound=false;
string svalue="";
[/blue]
[blue]b=iterator.Current.MoveToFirstAttribute();
while (b) {
if (iterator.Current.LocalName=="zzz") {
b=false;
bfound=true;
svalue=iterator.Current.Value;
} else )
b=iterator.Current.MoveToNextAttribute();
}
}
if (bfound) {
//svalue is your answer, do something
} else {
//the attribute zzz is not found, do something
}
iterator.Current.MoveToParent();[/blue]
//etc etc
[/tt]
 
>[self]} else )
should be read:
[tt]} else [red]{[/red][/tt]
 
tsuji
Even if my explanation was not at an university level - it's been a while since I've graduated - and not enough for you, you can state it normally, there is no need to trash me. BTW, your code does not work either with the file I have problems with.

What's wrong whit this? I've also tried with an empty string, but same result.
Code:
Attr = iterator.Current.GetAttribute("zzz", ns.DefaultNamespace);

I post below as an example 2 files, maybe I should have started with this.

correct XML file, your code and mines work
Code:
<?xml version="1.0" encoding="utf-8"  standalone="no" ?>
<invoice>
       <item>
           <code>100</code>
           <price currency = "Euro">9.95</price>
       </item>
       <item>
           <code>101</code>
           <price currency = "USD">29.95</price>
       </item>
</invoice>

"corrupted" XML file, nothing works. Do not ask me why it's corrupted, I just get it like this.
Code:
<?xml version="1.0" encoding="utf-8"  standalone="no" ?>
<invoice [red]xmlns="[URL unfurl="true"]http://www.does_not_exist.com"[/URL][/red]>
       <item>
           <code>100</code>
           <price currency = "Euro">9.95</price>
       </item>
       <item>
           <code>101</code>
           <price currency = "USD">29.95</price>
       </item>
</invoice>

vlad
 
The problem is not that getattribute() does not get anything; the problem is your iterator has nothing to iterate to begin with. (And you want people here to know the problem based on your "description"? and that I trash whatever it means?) I only showed you what kind of analysis can one make based on your description and showed you the implausible conclusion. What's wrong with that? You want me to pat on your back and said well-done and excellent effort?
[tt]
//etc etc
XmlNamespaceManager ns = new XmlNamespaceManager(navigator.NameTable);
ns.AddNamespace("dns","[ignore][/ignore]");
XPathExpression expr=navigator.Compile("/dns:invoice/dns:item/dns:price");
expr.SetContext(ns);
XPathNodeIterator iterator = navigator.Select(expr);
while (iterator.MoveNext()) {
Console.WriteLine(iterator.Current.Name + "\t" + iterator.Current.Value + "\t" + iterator.Current.GetAttribute("currency",String.Empty));
}
//etc etc
[/tt]
 
Thanks, that works and it's what I need, for the solution itself you deserve a star.

But why can't you help someone without trying to show how smart you are and how stupid other people are?


vlad
 
Thanks for the vote. I am _not_ trying to show how smart I am, - needless to add that "not" means not that "I am not trying to show...", but means "I am not smart". If I think I have to put something across to highlight what's wrong and why, I believe I have to say it straight, without ambiguity, maybe not like others; or I just pass. (That's as well why that I didn't response to the thread until you showed some real eagerness to have it resolved.) And treat each thread of its own merit. Since you're a helpful member to the site of your own merit in the large, I really shouldn't argue and the site owes you recognition. Thank you for your tolerance.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top