在C#中使用XmlReader在xml段中查找值

问题描述:

我正在使用XML阅读器来搜索我们使用的xml配置文件。我想找到某个键​​下的值,如果它们不存在,可以更改它们或添加它们。在C#中使用XmlReader在xml段中查找值

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> 
    </Configurations> 
</DBSimulatorConfigurations> 

到目前为止的代码......注释掉位不“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); 
     } 

    } 

但我希望做的就是找到和变化中寻找价值'Submit'或'Amend'等的值,或者如果没有输入'Submit',那么我会添加一个。

但首先我想能够找到并更改Test1的值。

+1

您不能使用LINQ to XML及其[SetElement方法](https://docs.microsoft.com/en-us/dotnet/api/system.xml.linq.xelement.setelementvalue?view=netframework- 4.7)? –

+0

如果您正在修改您的XML,那么使用LINQ to XML来实现这一点会更容易。请参阅[Linq to XML - 更新/更改XML文档的节点](https://*.com/q/331502/3744182)或[使用Linq的C#更新XML](https://*.com/q/1487653)开始。 – dbc

+0

如果你确实想用XmlReader和XmlWriter来实现XML的流转换,你可以从[为简单流转换组合XmlReader和XmlWriter类]开始(https://blogs.msdn.microsoft.com/mfussell/2005/02/12 /组合最XMLReader的 - 和 - 的XmlWriter类换简单串流-变换/)。 – dbc

这是一种方法,使用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

我收到代码错误。 “System.Xml.XmlException:根级别的数据无效,行1,位置1”。 xml文件的第一行是: John

+0

@john您的xml无效。 XDocument期望有效的xml。事实上,你提供的xml示例也是无效的,它缺少关闭我添加的'DBSimulatorConfigurations'节点。我的答案中的Xml应该是有效的,你可以用它来测试代码。要检查你的xml,你可以使用一些在线工具,如[this one](http://www.xmlvalidation.com/)或[this one](https://codebeautify.org/xmlvalidator) – Nino

+0

你列出的两个工具下面说我的xml是有效的。但我解决了这个问题,通过使用XDocument.Load而不是XDocument.Parse – John

这似乎工作,以找到价值和更新。我已经更新了它,因此我可以为特定值找到任何值。

//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"); 

这是做这件事最有效的方法吗?