扩展树结构XDcoument

时间:2017-09-22 07:01:45

标签: c# xml xpath xml-parsing linq-to-xml

我正在尝试扩展基于XDocument的树结构。
它应该能够添加部分和参数值组合作为属性
树的深度不固定。
因此,该函数应验证是否存在某些内容,如果不存在则添加它。

<Body>
 <SectionA>
   <SectionB paramB="valB" paramB2="val2">
    <SectionC paramB="valB" paramNEW="NEW">
    </SectionC>
    <SectionD>
      <SectionE>
      </SectionE>
    </SectionD>
   </SectionB>
  </SectionA>
</Body>

所以我写了以下内容

    public void Create(string treenode, string parameter, string value, XDocument doc)
    {
        treenode =treenode.Replace('\\','/');   
        string[] branch = treenode.Split('/');
        string tree = "";
        for (int i = 0; i < branch.Length; i++) // walk trough tree
        {
            tree = tree +"/"+ branch[i];
            bool exists = (bool)doc.XPathEvaluate("boolean("+tree+")");
            if (exists==false)  //...what goes here ?.
        }
    }

我对“什么在这里”之后使用的功能感到有点困惑。
因为树的深度可以变化。

1 个答案:

答案 0 :(得分:1)

这可以使用递归来解决。请尝试以下方法:

切入点

 void Entry()
 {
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(@"<Body>
                     <SectionA>
                       <SectionB paramB = 'valB' paramB2='val2'>
                        <SectionC paramB = 'valB' paramNEW='NEW'>
                        </SectionC>
                        <SectionD>
                          <SectionE>
                          </SectionE>
                        </SectionD>
                       </SectionB>
                      </SectionA>
                    </Body>");

    string treeNode = @"Body\SectionA\SectionB\SectionC\SectionX";
    Create(treeNode, "paramX", "valueX", doc);
  }

您现有的代码在这里

public void Create(string treeNode, string parameter, string value, XmlDocument doc)
        {
            treeNode = treeNode.Replace('\\', '/');
            string[] branch = treeNode.Split('/');
            string tree = "";
            for (int i = 0; i < branch.Length; i++) // walk trough tree
            {
                tree = tree + "/" + branch[i];
                XmlNode node = CreateXPath(doc, tree, parameter, value);
                //if (exists == false)  //...what goes here ?.
            }
        }

递归函数:

private XmlNode CreateXPath(XmlDocument doc, string xpath, string parameter, string value)
{
  return CreateXPath(doc, doc as XmlNode, xpath, parameter, value);
}

private XmlNode CreateXPath(XmlDocument doc, XmlNode parent, string xpath, string parameter, string value)
{
   string[] partsOfXPath = xpath.Trim('/').Split('/');
   string nextNodeInXPath = partsOfXPath.First();
   if (string.IsNullOrEmpty(nextNodeInXPath))
   {
      if (parent.Attributes[parameter] == null && parent.LocalName == xpath)
      {
        // Attribute not found, create it                        
        ((XmlElement)parent).SetAttribute(parameter, value);
      }
      return parent;
    }

    XmlNode node = parent.SelectSingleNode(nextNodeInXPath);
    if (node == null)
    {
       // node not found, create it and additionally add attributes                    
       node = parent.AppendChild(doc.CreateElement(nextNodeInXPath));
       ((XmlElement)node).SetAttribute(parameter, value);
    }
    // Call recursive
    string rest = String.Join("/", partsOfXPath.Skip(1).ToArray());
    return CreateXPath(doc, node, rest, parameter, value);
 }

得到以下输出:

<?xml version="1.0"?>
<Body>
 <SectionA>
  <SectionB paramB2="val2" paramB="valB">
   <SectionC paramB="valB" paramNEW="NEW">
    <SectionX paramX="valueX"/>
   </SectionC>
   <SectionD>
    <SectionE/>
   </SectionD>
  </SectionB>
 </SectionA>
</Body>