2017-07-31 3 views
1

J'utilise un lecteur XML pour rechercher dans un fichier de configuration XML que nous utilisons. Je veux trouver les valeurs sous une certaine clé et pouvoir les changer ou les ajouter si elles n'existent pas.Recherche d'une valeur dans un segment xml à l'aide de XmlReader en C#

XML Exemple

<DBSimulatorConfigurations> 
    <Configurations> 
    <DBSimulatorConfiguration> 
     <Key>Test1</Key> 
     <Submit>0</Submit> 
     <Amend>0</Amend> 
     <Update>0</Update> 
     <Delete>1</Delete> 
    <ResponseTimeInSeconds>100</ResponseTimeInSeconds> 
    </DBSimulatorConfiguration> 
    <DBSimulatorConfiguration> 
     <Key>Test2</Key> 
     <Submit>0</Submit> 
     <AutoUpdate>0</AutoUpdate> 
     <Amend>0</Amend> 
     <Update>0</Update> 
     <Delete>1</Delete> 
    <ResponseTimeInSeconds>100</ResponseTimeInSeconds> 
    </DBSimulatorConfiguration> 
    <DBSimulatorConfiguration> 
    </Configurations> 
</DBSimulatorConfigurations> 

code jusqu'à présent ... commenté peu ne trouve pas la valeur dans « Test1 »

XmlReader reader = XmlReader.Create("C:\\<path>\\DBConfigs.xml"); 
while(reader.Read()) 
{ 
    if (reader.ReadToDescendant("Key")) 
    { 
     reader.Read(); 
     if (reader.Value == "Test1") 
     { 
      Console.WriteLine("Found_1 {0}", reader.Value); 
      // Doesn't work :( 
      // reader.Read(); 
      //if (reader.ReadToDescendant("Submit")) { 
      // Console.WriteLine("Value for Submit is {0}", reader.Value); 
      //} 
     } 

     if (reader.Value == "Test2") 
     { 
      Console.WriteLine("Found_2 {0}", reader.Value); 
     } 

     reader.Read(); //this moves reader to next node which is text 
     if (reader.ReadToDescendant("Full.2")) { 
      Console.WriteLine("Found {0}", reader.Value); 
     } 

    } 

Mais ce que je veux faire est alors trouver et changement la valeur pour 'Soumettre' ou 'Modifier' etc ou s'il n'y a pas d'entrée 'Envoyer' alors j'en ajouterai une.

Mais d'abord, j'aimerais pouvoir trouver et modifier les valeurs de Test1.

+1

Tu ne peux pas utiliser LINQ pour XML et sa [méthode setElement] (https://docs.microsoft.com/en-us/dotnet/api/system.xml.linq.xelement.setelementvalue?view=netframework- 4.7)? –

+0

Si vous modifiez votre XML, il sera beaucoup plus facile d'utiliser LINQ to XML pour le faire. Voir [Linq to XML - mettre à jour/modifier les nœuds d'un document XML] (https://stackoverflow.com/q/331502/3744182) ou [Mettre à jour XML avec C# en utilisant Linq] (https://stackoverflow.com/q/1487653) pour commencer. – dbc

+0

Si vous voulez vraiment, vraiment faire des transformations en flux continu de XML en utilisant simplement XmlReader et XmlWriter, vous pouvez commencer par combiner les classes XmlReader et XmlWriter pour des transformations en continu simples (https://blogs.msdn.microsoft.com/mfussell/2005/02/12/combination-the-xmlreader-et-xmlwriter-classes-for-simple-streaming-transformations /). – dbc

Répondre

0

Voici une approche, en utilisant XDocument:

string xml = @" 
<DBSimulatorConfigurations> 
    <Configurations> 
    <DBSimulatorConfiguration> 
     <Key>Test1</Key> 
     <Submit>0</Submit> 
     <Amend>0</Amend> 
     <Update>0</Update> 
     <Delete>1</Delete> 
    <ResponseTimeInSeconds>100</ResponseTimeInSeconds> 
    </DBSimulatorConfiguration> 
    <DBSimulatorConfiguration> 
     <Key>Test2</Key> 
     <Submit>0</Submit> 
     <AutoUpdate>0</AutoUpdate> 
     <Amend>0</Amend> 
     <Update>0</Update> 
     <Delete>1</Delete> 
    <ResponseTimeInSeconds>100</ResponseTimeInSeconds> 
    </DBSimulatorConfiguration> 
    <DBSimulatorConfiguration> 
    </DBSimulatorConfiguration> 
    </Configurations> 
</DBSimulatorConfigurations>"; 

XDocument xdoc = XDocument.Parse(xml); 
//search for all nodes with <DBSimulatorConfiguration> element 
var elements = xdoc.Root.Elements().Elements().Where(x => x.Name == "DBSimulatorConfiguration"); 
//iterate through all those eleemnt 
foreach (var element in elements) 
{ 
    //now find it's child named Submit 
    var submitElement = element.Elements().FirstOrDefault(x => x.Name == "Submit"); 
    //if such element is found 
    if (submitElement != null) 
    { 
     //here you can change Submit element, like this: 
     // submitElement.Value = "abc"; 
     //or you can check for something 
     if (submitElement.ElementsBeforeSelf().Any(x=> x.Name == "Key" && x.Value== "Test2")) 
     { 
      //this is submitElement which is after element named Key with value Test2 
      submitElement.Value = "some specific value"; 
     } 
    } 
    else 
     element.Add(new XElement("Submit", 999)); 
} 
+0

Je reçois une erreur avec le code. "System.Xml.XmlException: les données au niveau de la racine ne sont pas valides Ligne 1, position 1." Les premières lignes du fichier xml sont: John

+0

votre xml @John est pas valide. XDocument attend un fichier XML valide. En fait, l'échantillon xml que vous avez fourni en question n'était pas valide non plus, il manquait le noeud fermant 'DBSimulatorConfigurations' que j'ai ajouté. Xml dans ma réponse devrait être valide et vous pouvez tester le code avec. Pour vérifier votre fichier XML, vous pouvez utiliser certains des outils en ligne comme [celui-ci] (http://www.xmlvalidation.com/) ou [celui-ci] (https://codebeautify.org/xmlvalidator) – Nino

+0

Les deux outils que vous avez listés ci-dessous disent que mon xml est valide. Mais j'ai résolu le problème en utilisant XDocument.Load au lieu de XDocument.Parse – John

1

Cela semble travailler pour trouver la valeur et le mettre à jour. Je l'ai mis à jour afin que je puisse trouver n'importe quelle valeur pour une valeur particulière.

//search for all nodes with <DBSimulatorConfiguration> element 
string xml = "<path>.DBConfig.xml"; 
XDocument xdoc = XDocument.Load(xml); 
var elements = xdoc.Root.Elements().Elements().Where(x => x.Name == "DBSimulatorConfiguration"); 
//iterate through all those eleemnt 

foreach (var element in elements) 
{ 
    //Console.WriteLine("Empty {0}", element.Value); 
    //now find it's child named Submit 
    var configKey = element.Elements().FirstOrDefault(x => x.Name == "Key"); 
    var configSubmit = element.Elements().FirstOrDefault(x => x.Name == "Submit"); 
    var configAmend = element.Elements().FirstOrDefault(x => x.Name == "Amend"); 
    var configUpdate = element.Elements().FirstOrDefault(x => x.Name == "Update"); 
    var configDelete = element.Elements().FirstOrDefault(x => x.Name == "Delete"); 

    //if such element is found 
    if (configSubmit != null) 
    { 
     if (configKey.ElementsBeforeSelf().Any(x => x.Name == "Key" && x.Value == "Test1")) 
     { 
      Console.WriteLine("Found Key for Test1 {0}", configKey.Value); 
     } 
     if (configSubmit.ElementsBeforeSelf().Any(x => x.Name == "Key" && x.Value == "Test1")) 
     { 
      configSubmit.Value = "1"; 
      Console.WriteLine("Submit value is updated to {0}", configSubmit.Value);   
     } 
     if (configAmend.ElementsBeforeSelf().Any(x => x.Name == "Key" && x.Value == "Test1")) 
     { 
      Console.WriteLine("Amend value is: {0}", configAmend.Value); 
     } 
     if (configUpdate.ElementsBeforeSelf().Any(x => x.Name == "Key" && x.Value == "Test1")) 
     { 
      Console.WriteLine("Update value is: {0}", configUpdate.Value); 
     } 
    } 
} 
xdoc.Save("<path>.DBConfig.xml"); 

Est-ce le moyen le plus efficace de le faire?