阅读和修改xmlNodes而不影响他们的孩子

时间:2012-02-29 11:33:52

标签: c# xml

我有一大堆我想要处理的XML。我在C#中写这个,但会用psuedocode来解释我想做什么。如果您需要更多信息,请与我们联系。在C#中,我将XML加载到XMLDocument中,如下所示:

XmlDocument templateDoc = new XmlDocument();
            templateDoc.LoadXml(selectionTemplate);
            XmlNodeList orderNodes = templateDoc.GetElementsByTagName("order");

XML:

<sort>
  <order name="panelCode">
  <panelCode/>
  </order>
  <order name="panelName">
  <panelName/>
  </order>
  <order name="panelPart">
  <panelPart/>
  </order>
  <order name="numberLayers">descending
  <numberLayers/>
    <panelCode>ascending|ascending
    </panelCode>
  </order>
</sort>

伪码:

foreach ( orderNode )
{
  if ( order node title matches my string )
  {
    if ( order node text is ascending or descending ) //This check Im struggling with as I only want to check the order node text and not include any child node text in the comparison. 
    {
       switch ascending with descending and vice versa //If i set the inner text of the order node it will effect the text contained within its child nodes.
    }
    else //order node text is blank
    {
       set ordernode text to be ascending //Again its the child nodes that could cause an issue. 
    }
  }
  else // order node title does not match string
  {
     if ( order node text is ascending or descending )
     {
       remove order node text whilst maintaining the inner text of any child nodes. //Again its the child nodes that could cause an issue.
     }
  }
}

作为一个如何运作的例子......

如果我的字符串是panelCode,我会遍历所有订单节点。第一个是匹配,所以我将该订单节点的值设置为“升序”。然后我会遍历其余的订单节点,寻找具有升序/降序值的任何订单节点。这对于numberLayers顺序节点是正确的,其值I我想设置为“”但保持子节点的值,例如升序。所以解析后的文档看起来如下所示。

新XML:

<sort>
  <order name="panelCode">ascending
  <panelCode/>
  </order>
  <order name="panelName">
  <panelName/>
  </order>
  <order name="panelPart">
  <panelPart/>
  </order>
  <order name="numberLayers">
  <numberLayers/>
    <panelCode>ascending|ascending
    </panelCode>
  </order>
</sort>

如果我拥有的字符串是numberLayers,那么提供的XML将如下所示:

<sort>
  <order name="panelCode">
  <panelCode/>
  </order>
  <order name="panelName">
  <panelName/>
  </order>
  <order name="panelPart">
  <panelPart/>
  </order>
  <order name="numberLayers">ascending
  <numberLayers/>
    <panelCode>ascending|ascending
    </panelCode>
  </order>
</sort>

1 个答案:

答案 0 :(得分:1)

好的,我想我有你的答案:

您的XML结构有点棘手的是,您在同一级别上有文本节点和其他xml节点(例如<panelCode/>)。处理它的技巧是XPath表达式中的text()选择器。这就是我要写的内容:

string targetName = "numberLayers";

// grab the first matching order node
XmlNode matchOrderNode= xmldoc.SelectSingleNode(
                  "//order[@name='" + targetName + "']"); 

// try to grab the first #text leaf node, if not existing, append new 
XmlNode matchTextChildNode = matchOrderNode.SelectSingleNode("./text()"); 
if (matchTextChildNode == null)
{
       matchTextChildNode = matchOrderNode.AppendChild(xmldoc.CreateTextNode(string.Empty));
}

// determine whether 'ascending' is set already --> toggle
string textToSetAfterwards = "ascending";
if (matchTextChildNode.Value == "ascending")
{
    textToSetAfterwards = "descending";
}

// clear all ascending/descending text nodes
foreach (XmlNode orderNode in xmldoc.SelectNodes(
       "//order[text()='ascending' or text()='descending']/text()"))
{
    orderNode.Value = string.Empty;
}

// re-set only the matched node's value
matchTextChildNode.Value = textToSetAfterwards;

您可以使用XPath直接选择#text-leaf-nodes。那些#text节点实际上在.Value属性中有纯文本内容(例如“升序”或“降序”),可以读取和设置!