tags:

views:

19

answers:

2

El Padrino showed a solution:

http://stackoverflow.com/questions/367730/how-to-change-xml-value-file-using-c

where an xml element can be loaded directly (no for each..), edited and saved!

My xml is:

<?xml version="1.0" encoding="ISO-8859-8"?>
<g>
  <page no="1" href="page1.xml" title="נושא 1">
    <row>
      <pic pos="1" src="D:\RuthSiteFiles\webSiteGalleryClone\ruthCompPics\C_WebBigPictures\100CANON\IMG_0418.jpg" width="150" height="120">1</pic>
    </row>
  </page>
</g>

and I need to select a node by two attributes(1. "no" in the page tag and "pos" in the pic tag)

I've found : http://stackoverflow.com/questions/1716287/how-to-access-a-xml-node-with-attributes-and-namespace-using-selectsinglenode

where direct access is possible but beside the fact that I dont understand the solution, I think it uses the xpath object which can't be modified and save changes.

What's the best way to

  1. access directly an xml node (I'm responsible that the node will be unique)
  2. edit that node
  3. save changes to the xml

Thanks Asaf

+1  A: 

You can use the same pattern as the first answer you linked to, but you will need to include the conditions on the attributes in the XPath. Your basic XPath would be g/page/row/pic. Since you want the no attribute of page to be 1, you add [@no='1'] as a predicate on page. So, the full XPath query is something like g/page[@no='1']/row/pic[@pos='1']. SelectSingleNode will return a mutable XmlNode object, so you can modify that object and save the original document to save changes.

Putting the XPath together with El Padrino's answer:

//Here is the variable with which you assign a new value to the attribute
string newValue = string.Empty;
XmlDocument xmlDoc = new XmlDocument();

xmlDoc.Load(xmlFile);

XmlNode node = xmlDoc.SelectSingleNode("g/page[@no='1']/row/pic[@pos='1']");
node.Attributes["src"].Value = newValue;

xmlDoc.Save(xmlFile);

//xmlFile is the path of your file to be modified
Quartermeister
+1 Thanks, it worked for me.
Asaf
A: 

Use the new, well-designed XDocument/XElement instead of the old XmlDocument API.

In your example,

XDocument doc = XDocument.Load(filename);

var pages = doc.Root.Elements("page").Where(page => (int?) page.Attribute("no") == 1);
var rows = pages.SelectMany(page => page.Elements("row"));
var pics = rows.SelectMany(row => row.Elements("pic").Where(pic => (int?) pic.Attribute("pos") == 1));

foreach (var pic in pics)
{
    // outputs <pic pos="1" src="D:\RuthSiteFiles\webSiteGalleryClone\ruthCompPics\C_WebBigPictures\100CANON\IMG_0418.jpg" width="150" height="120">1</pic>
    Console.WriteLine(pic);

    // outputs 1
    Console.WriteLine(pic.Value);

    // Changes the value
    pic.Value = 2;
}

doc.Save(filename);
Timwi
The XDocument helped me do every operation I need on the xml file with one object.Yet I could not do something like a= pic[0];Any way thanks alot
Asaf
@Asaf: If you write `.ToArray()` at the end of the `pics` declaration, then you can go `pics[0]`. However, if you don’t need such an array, then `pic.First()` is the most efficient solution.
Timwi