在C#中实时编辑xml。删除包含特定值的节点

时间:2016-07-08 08:10:37

标签: c# xml

我有一个类似这样的xml文档:

<?xml version="1.0" encoding="UTF-16"?>
<Recordset>
  <Table>Recordset</Table>
  <Rows>
    <Row>
      <Fields>
        ...
        <Field>
          <Alias>StatusName</Alias>
          <Value>Scheduled</Value>
        </Field>
        <Field>
          <Alias>U_Revision</Alias>
          <Value>code00</Value>
        </Field>
        <Field>
          <Alias>U_Quantity</Alias>
          <Value>10.000000</Value>
        </Field>
        <Field>
          <Alias>U_ActualQty</Alias>
          <Value>0.000000</Value>
        </Field>
        ...
      </Fields>
    </Row>
    ...
    <Row>
      <Fields>
        ...
        <Field>
          <Alias>StatusName</Alias>
          <Value>Scheduled</Value>
        </Field>
        <Field>
          <Alias>U_Revision</Alias>
          <Value>code00</Value>
        </Field>
        <Field>
          <Alias>U_Quantity</Alias>
          <Value>150.000000</Value>
        </Field>
        <Field>
          <Alias>U_ActualQty</Alias>
          <Value>0.000000</Value>
        </Field>
        ...
      </Fields>
    </Row>
  </Rows>
</Recordset>

我在字段中使用StatusName的别名具有不同的值。有一些Scheduled,notScheduled,Realeased,Finished等值。我想要做的是删除包含具有别名StatusName的节点的每个节点,并且值可以说是Scheduled或Finished。

我正在考虑以这种方式做或多或少,但是我做错了。愿任何人让我走正轨吗?

            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(xml);
            XmlNodeList nodes = xmlDocument.SelectNodes("//Rows[@StatusName='Finished']");
            for (int i = nodes.Count - 1; i >= 0; i--)
            {
                nodes[i].ParentNode.RemoveChild(nodes[i]);
            }
            var newXml = nodes.ToString();

如果包含别名StatusName,我想删除整个节点,具体值就是说完成。

我希望结果是新的字符串变量。

2 个答案:

答案 0 :(得分:2)

我喜欢使用xml处理DataTable,我觉得很容易。 我使用DataTable来处理您的节点。 所以,我拿了你的xml文件并为你写了一些可能对你有用的代码:

//READ THE XML FILE
XmlDocument xmlDoc = new XmlDocument();
//My path
xmlDoc.LoadXml(Properties.Resources.test);

//Read the xml file into a dataSet
DataSet ds = new DataSet();
XmlNodeReader xnr = new XmlNodeReader(xmlDoc);
ds.ReadXml(xnr);

//Your data will be store in the 4's dataTable of the dataSet ( the <field> )
for(int i=0;i<ds.Tables[4].Rows.Count;i++)
{
    //Check the value as you wish
    //Here i want to suppress all the <Field> nodes with <Value> = "Scheduled"
    if ( ds.Tables[4].Rows[i]["Value"].ToString().Equals("Scheduled"))
    {
        //RemoteAt will remove all the node, so the node <Field> in your example data
        ds.Tables[4].Rows.RemoveAt(i);
        //If you want to only remove the node <Value>  (and not all the <Field> node ) just do ds.Tables[4].Rows["Value"]=null;
     }
}
//Write your new content in a new xml file

//As you wanted here you just read the new xml file created as a string
using (var stringWriter = new StringWriter())
using (var xmlTextWriter = XmlWriter.Create(stringWriter))
{
    ds.WriteXml(xmlTextWriter);
    xmlTextWriter.Flush();
    stringWriter.GetStringBuilder().ToString();
    //Here the result is in stringWriter,  and  there is 6 <Field> nodes, and not 8 like before the suppress
}

//If you want to create a new xml file with the new content just do 
ds.WriteXml(yourPathOfXmlFile);
//( like rewriting the previous xml file )

答案 1 :(得分:2)

我假设您要删除符合条件的整个<Row> 即,

<Row>
  <Fields>
    ...
    <Field>
      <Alias>StatusName</Alias>
      <Value>Finished</Value>
    </Field>
  </Fields>
</Row> 

所需的XPath:

//Row[Fields[Field[Alias[text()='StatusName'] and Value[text() = 'Finished']]]] 

C#

string xPath = @"//Row[Fields[Field[Alias[text()='StatusName'] and Value[text() = 'Finished']]]]";
var nodes = xmlDocument.SelectNodes(xPath);
for (int i = nodes.Count - 1; i >= 0; i--)
{
    nodes[i].ParentNode.RemoveChild(nodes[i]);
}
var newXml = xmlDocument.OuterXml;