2009-06-14 7 views
0

Comme dans, si j'ai un document XMLC# SelectSingleNode - Peut-il être utilisé récursivement?

<root a="value"> 
    <item name="first"> 
     x 
     <foo name = "firstgrandchild">There is nothing here</foo> 
     y 
     <foo name = "secondgrandchild">There is something here</foo> 
    </item> 
    <item name="second"> 
     xy 
     <foo/> 
     ab 
    </item> 
</root> 

Je veux d'abord trouver la première occurrence de noeud « élément » et ensuite mettre à jour l'attribut, et je veux mettre à jour la première occurrence de noeud « foo "puis mettre à jour l'attribut etc.,

Mon code est comme ci-dessous

myDoc.Load("Items2.xml"); 
myNode = myDoc.DocumentElement; 
mySearchNode = myNode.SelectSingleNode("/root/item"); 
mySearchNode.Attributes["name"].Value = "Joel"; 
Console.WriteLine(mySearchNode.OuterXml); 
mySearchChildNode = mySearchNode.SelectSingleNode("/item/foo"); 
Console.WriteLine(mySearchChildNode.OuterXml); 

alors, la première recherche et mise à jour de l'attribut fonctionne très bien, la seconde échoue mySearchNode.SelectSingleNode retourne null. Question - Y at-il quelque chose de fondamentalement faux avec ce code? Pourquoi le SelectSingleNode ne fonctionne pas comme prévu dans la seconde instance, en ce qui le concerne, je l'exécute sur un XmlNode de type Element.

Veuillez aider.

Merci beaucoup,

Répondre

5

Votre deuxième requête XPath doit être sans le slash./signifie "racine du document". Si vous omettez la barre oblique, la requête sera relative à votre variable mySearchNode. Vous ne devez pas non plus inclure "item", votre requête est relative au nœud "item" que vous avez sélectionné. Dans le code:

myDoc.Load("Items2.xml"); 
myNode = myDoc.DocumentElement; 
mySearchNode = myNode.SelectSingleNode("/root/item"); 
mySearchNode.Attributes["name"].Value = "Joel"; 
Console.WriteLine(mySearchNode.OuterXml); 
mySearchChildNode = mySearchNode.SelectSingleNode("foo"); 
Console.WriteLine(mySearchChildNode.OuterXml); 
2

mySearchNode est le nœud item, donc si foo est un enfant de item votre deuxième XPath doit simplement être "foo"

0

Vous pouvez faire un SelectNodes, puis faire une boucle sur tous les nœuds d'élément. Pour chaque article, vous devez en outre faire un SelectNodes sur les noeuds foo. Vous devriez vérifier le nombre de nœuds et également si le nom d'attribut existe ou non pour les nœuds item et foo. Vous pouvez utiliser ce code:

/// <summary> 
/// Changes the xml in sourceFileName and writes the changed xml to destFileName 
/// </summary> 
public static void ProcessNames(string sourceFileName, string destFileName) 
{ 
    XmlDocument xmlDoc = new XmlDocument(); 
    XmlTextWriter xtw = null; 
    xmlDoc.Load(sourceFileName); 

    try 
    { 
     // Parse through all the item nodes and process them 
     XmlNodeList itemList = xmlDoc.SelectNodes("//root/item"); 

     if (itemList.Count > 0) 
     { 
      foreach (XmlNode item in itemList) 
      { 
       // Change the name attribute, if it exists 
       if (item.Attributes["name"] != null) 
       { 
        string newItemName = item.Attributes["name"].Value + "Joel"; 
        item.Attributes["name"].Value = newItemName; 
       } 

       // Parse through all the foo nodes and process them 
       XmlNodeList fooList = item.SelectNodes("foo"); 

       if (fooList.Count > 0) 
       { 
        foreach (XmlNode foo in fooList) 
        { 
         // Change the name attribute, if it exists 
         if (foo.Attributes["name"] != null) 
         { 
          string newFooName = foo.Attributes["name"].Value + "Joel"; 
          foo.Attributes["name"].Value = newFooName; 
         } 
        } 
       } 

      } 

      xtw = new XmlTextWriter(destFileName, Encoding.UTF8); 
      xmlDoc.WriteContentTo(xtw); 
     } 

    } 
    finally 
    { 
     xtw.Close(); 
    } 
} 
Questions connexes