Parsing XML nodes by Attribute

G

Grant

I have this simple xml file which wont ever get beyong 3 nodes deep. I need
to get the value of the child node of any node with an id of '63'. So fir
instance I would be returned 'False' from the example below.

Ive attached an XML snippet and a cC# code snippet. The piece of code is not
working as I am not too familiour with parsing XML files.I think I need to
load the attributes into an array and loop through them to check for that
value. Could anyone help me with this? Is there an wasier way?

Thanks,
Grant

-------Sample XML-----------------

<session-data>
<attr-inst id="p1" state="known">
<val>Wilma Flintstone</val>
</attr-inst>
<attr-inst id="63" state="known">
<val>false</val>
</attr-inst>
</session-data>

----------Sample C# Code------------

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(fileName);
XmlNodeList nodeList = xmlDoc.SelectNodes("//session-data/attr-inst");
foreach (XmlNode node in nodeList)
{
if ( node.Attributes["id"].Attributes == "63")
{
node.Attributes["id"].FirstChild.Value = newDate;
}
}
 
M

Martin Honnen

Grant said:
I have this simple xml file which wont ever get beyong 3 nodes deep. I need
to get the value of the child node of any node with an id of '63'. So fir
instance I would be returned 'False' from the example below.

If you only want to read out values then XPathDocument is one way to do
it, it is easy to write one XPath expression selecting the nodes as
described above:

XPathDocument xpathDocument = new XPathDocument(@"test2005031602.xml");
XPathNavigator xpathNavigator = xpathDocument.CreateNavigator();
XPathNodeIterator nodeIterator =
xpathNavigator.Select(@"/session-data/attr-inst[@id = '63']/*");
while (nodeIterator.MoveNext()) {
Console.WriteLine("Found value \"{0}\".",
nodeIterator.Current.Value);
}
 
G

Grant

I managed to find a way of going directly to that specific node using the
code below. What I need to do now is modify the child node value that it
picks up. Problem is it is wiping out the '<val>' and '</val>'part of the
node. So when I run the code from the code snippet section below, against
the Original XML snippet, I get the modified XML output. You can see it has
deleted the child node and simply added the new value as a value of its
parent node.

how do I simply change the value of that node Ive found?
Thanks,
Grant


------Original XML-----------
<attr-inst id="63" state="known">
<val>false</val>
</attr-inst>

------modified XML-----------
<attr-inst id="63" state="known">true</attr-inst>

--------Code Snippet------------
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(fileName);
XmlNodeList nodeList = xmlDoc.SelectNodes("//session-data/attr-inst");
XmlNode findnode;
XmlElement root = xmlDoc.DocumentElement;
findnode = root.SelectSingleNode("descendant::attr-inst[@id='63']");
findnode.InnerXml = "true";
xmlDoc.Save(fileName);



Martin Honnen said:
I have this simple xml file which wont ever get beyong 3 nodes deep. I
need to get the value of the child node of any node with an id of '63'.
So fir instance I would be returned 'False' from the example below.

If you only want to read out values then XPathDocument is one way to do
it, it is easy to write one XPath expression selecting the nodes as
described above:

XPathDocument xpathDocument = new
XPathDocument(@"test2005031602.xml");
XPathNavigator xpathNavigator = xpathDocument.CreateNavigator();
XPathNodeIterator nodeIterator =
xpathNavigator.Select(@"/session-data/attr-inst[@id = '63']/*");
while (nodeIterator.MoveNext()) {
Console.WriteLine("Found value \"{0}\".",
nodeIterator.Current.Value);
}
 
M

Martin Honnen

Grant said:
I managed to find a way of going directly to that specific node using the
code below. What I need to do now is modify the child node value that it
picks up. Problem is it is wiping out the '<val>' and '</val>'part of the
node. So when I run the code from the code snippet section below, against
the Original XML snippet, I get the modified XML output. You can see it has
deleted the child node and simply added the new value as a value of its
parent node.

You do not access the right node, as suggested use the XPath expression
@"/session-data/attr-inst[@id = '63']/*"
then you have the element child nodes you are looking for, perhaps if
you know the element name of the child node you want
@"/session-data/attr-inst[@id = '63']/val"
then you can use SelectSingleNode and change
node.InnerText = "true";
Or access the text node itself e.g.
@"/session-data/attr-inst[@id = '63']/val/text()"
then use
node.Value = "true";
 
G

Grant

That works great - So its simply standard Xpath expressions that can be used
to browse nodes, exactly the same as XSLT.

Thanks for your help,
Grant

Martin Honnen said:
I managed to find a way of going directly to that specific node using the
code below. What I need to do now is modify the child node value that it
picks up. Problem is it is wiping out the '<val>' and '</val>'part of the
node. So when I run the code from the code snippet section below, against
the Original XML snippet, I get the modified XML output. You can see it
has deleted the child node and simply added the new value as a value of
its parent node.

You do not access the right node, as suggested use the XPath expression
@"/session-data/attr-inst[@id = '63']/*"
then you have the element child nodes you are looking for, perhaps if you
know the element name of the child node you want
@"/session-data/attr-inst[@id = '63']/val"
then you can use SelectSingleNode and change
node.InnerText = "true";
Or access the text node itself e.g.
@"/session-data/attr-inst[@id = '63']/val/text()"
then use
node.Value = "true";
 
G

Guest

Your findnode has a child node below it <val> so you should be
modifying the value of that.
Try replacing
findnode.InnerXml = "True";
with
XmlElement val_node = (XmlElement)findnode.FirstChild;
val_node.NodeValue = "True;
 
G

Grant

Is that the same as what I have currently? One last question on this: How do
I modify the Node ID?? So in the example XML I need id='63' to become
id='999' or whatever. In my problematic code section I removed the "/val");"
section because I dont want it looking at the child node - but when it
doesnt change the attribute id value for some reason - it tells me "the
expression passed to this method must result in a nodeset"

What am I doing wrong?
Thanks.


----------Problematic Code: setting Attribute ID------------
findnode = root.SelectSingleNode(@"/session-data/attr-inst/[@id = '" +
FactIDToReplace + "']");
if ( findnode != null )
{
findnode.Attributes["ID"].InnerText = newValue;
}

----------XML------------
<attr-inst id="63" state="known">
<val>false</val>
</attr-inst>

----------Working Code------------
findnode = root.SelectSingleNode(@"/session-data/attr-inst[@id = '" +
FactIDToReplace + "']/val");
if ( findnode != null )
{
findnode.InnerText = newValue;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top