tags:

views:

126

answers:

3

I am a beginner to XML and XPath in C#. Here is an example of my XML doc:

 <root>
   <folder1>
   ...
   <folderN>
      ...
      <nodeMustExist>...
      <nodeToBeUpdated>some value</nodeToBeUpdated>
  ....
 </root>

What I need is to update the value of nodeToBeUdpated if the node exists or add this node after the nodeMustExist if nodeToBeUpdated is not there. The prototype of the function is something like this:

void UpdateNode(
                  xmlDocument xml, 
                  string nodeMustExist, 
                  string nodeToBeUpdte, 
                  string newVal
               )
{
   /*

   search for XMLNode with name = nodeToBeUpdate in xml 
   to XmlNodeToBeUpdated (XmlNode type?)
   if (xmlNodeToBeUpdated != null)
   {
      xmlNodeToBeUpdated.value(?) = newVal;
   }
   else
   {
      search for nodeMustExist in xml to xmlNodeMustExist obj
      if ( xmlNodeMustExist != null )
      {
          add xmlNodeToBeUpdated as next node
          xmlNodeToBeUpdte.value = newVal;
       }
    }

   */
}

Maybe there are other better and simplified way to do this. Any advice?

By the way, if nodeToBeUpdated appears more than once in other places, I just want to update the first one.

A: 

Have a look at the SelectSingleNode method MSDN Doc

your xpath wants to be something like "//YourNodeNameHere" ;

once you have found that node you can then traverse back up the tree to get to the 'nodeMustExist' node:

XmlNode nodeMustExistNode = yourNode.Parent["nodeMustExist];
Adrian
+1  A: 

The XPath expression that selects all instances of <nodeToBeUpdated> would be this:

/root/folder[nodeMustExist]/nodeToBeUpdated

or, in a more generic form:

/root/folder[*[name() = 'nodeMustExist']]/*[name() = 'nodeToBeUpdated']

suitable for:

void UpdateNode(xmlDocument xml, 
                string nodeMustExist, 
                string nodeToBeUpdte, 
                string newVal)
{
  string xPath = "/root/folder[*[name() = '{0}']]/*[name() = '{1}']";
  xPath = String.Format(xPath, nodeMustExist, nodeToBeUpdte);

  foreach (XmlNode n in xml.SelectNodes(xPath))
  {
    n.Value = newVal;
  }
}
Tomalak
+1  A: 

This is to update all nodes in folder:

public void UpdateNodes(XmlDocument doc, string newVal)
        {
            XmlNodeList folderNodes = doc.SelectNodes("folder");

            if (folderNodes.Count > 0)
            foreach (XmlNode folderNode in folderNodes)
            {
                XmlNode updateNode = folderNode.SelectSingleNode("nodeToBeUpdated");
                XmlNode mustExistNode = folderNode.SelectSingleNode("nodeMustExist"); ;
                if (updateNode != null)
                { 
                    updateNode.InnerText = newVal;
                }
                else if (mustExistNode != null)
                {
                    XmlNode node = folderNode.OwnerDocument.CreateNode(XmlNodeType.Element, "nodeToBeUpdated", null);
                    node.InnerText = newVal;
                    folderNode.AppendChild(node);
                }

            }
        }

If you want to update a particular node, you cannot pass string nodeToBeUpdte, but you will have to pass the XmlNode of the XmlDocument. I have omitted the passing of node names in the function since nodes names are unlikely to change and can be hardcoded. However, you can pass these to the functions and use the strings instead of hardcoded node names.

Rashmi Pandit