将兄弟节点插入xml文档

时间:2014-05-10 19:31:55

标签: c# .net xml xpath xmldocument

我有一个使用XmlDocument加载XML String的.net Web应用程序。 XML的格式如下:

<Sections name="Section Opening Page" PageContentID="201" Template="ReportTags">
  <Chapter Name="Introduction" PageContentID="202" Template="ReportTags">
    <Pages Name="Why this Document?" PageContentID="203" Template="ReportTags" />
    <Pages Name="Target Audience" PageContentID="204" Template="ReportTags" />
  </Chapter>
  <Chapter Name="Detailed Results" PageContentID="205" Template="ReportTags">
    <Pages Name="Question List" PageContentID="206" Template="ReportTags" />
    <Pages Name="Answers" PageContentID="207" Template="ReportTags" />
    <Pages Name="Comments" PageContentID="208" Template="ReportTags" />
  </Chapter>
  <Chapter Name="Appendix 1" PageContentID="209" Template="ReportTags">
    <Pages Name="Page 1" PageContentID="210" Template="ReportTags" />
    <Pages Name="Page 2" PageContentID="211" Template="ReportTags" />
    <Pages Name="Page 3" PageContentID="212" Template="ReportTags" />
  </Chapter>
  <Chapter Name="Appendix 2" PageContentID="213" Template="ReportTags">
    <Pages Name="Page 1" PageContentID="214" Template="ReportTags" />
    <Pages Name="Page 2" PageContentID="215" Template="ReportTags" />
  </Chapter>
</Sections>

作为一个例子,我试图在“&#39;章节”下插入一个新的节点。命名&#39;详细结果&#39; BETWEEN&#39; Page&#39;命名问题清单&#39;和&#39;答案&#39;。我用来执行此操作的代码如下:

try
{
string sPath = "Sections/Chapter/Pages[@PageContentID='" + selectedNode.Value + "']";
XmlNode xmlNode = xmlDoc.SelectSingleNode(sPath);

XmlElement xNewChild = xmlDoc.CreateElement("Pages");
xNewChild.SetAttribute("Name", "Another New Page");
xNewChild.SetAttribute("PageContentID", Guid.NewGuid().ToString());
xNewChild.SetAttribute("Template", "ReportTags");

xmlDoc.DocumentElement.InsertAfter(xNewChild, xmlNode); 
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}

然而,它不起作用,我的新节点没有插入正确的位置,它被插入顶部。

非常感谢任何帮助!!

2 个答案:

答案 0 :(得分:5)

您确定xmlNode正在返回您认为的节点吗?使用调试器逐步完成它。

如果是null,那么您插入的节点将被添加为您描述的DocumentElement的子节点。如果它返回Pages节点,那么您应该得到一个异常'参考节点不是该节点的子节点'。

这是相当自我解释的。代码:

doc.DocumentElement.InsertAfter(xNewChild, xmlNode); 

应该是:

xmlNode.ParentNode.InsertAfter(xNewChild, xmlNode);

这说,如果可能的话,我会使用XDocument,这是XLinq的一部分。 API更好更好功能更强大,通常性能更高。一个例子:

var element = x.Descendants("Pages").Single(e => e.Attribute("PageContentID").Value == "206");

var newElement = new XElement("Pages",
                                new XAttribute("Name", "Another New Page"),
                                new XAttribute("PageContentID", Guid.NewGuid().ToString()),
                                new XAttribute("Template", "ReportTags"));

element.AddAfterSelf(newElement);

答案 1 :(得分:1)

如果您不介意使用Linq-To-Xml

XDocument xmlDocument = XDocument.Load("asd.xml");
        try
        {
            var root = xmlDocument.Root;
            var pages = root.Elements("Chapter").Elements("Pages");
            var mypage = pages.Where(p => p.Attribute("PageContentID").Value == "206").FirstOrDefault();
            XElement xNewChild = new XElement("Pages", new XAttribute("Name", "Another New Page"), new XAttribute("PageContentID", Guid.NewGuid().ToString()), new XAttribute("Template", "ReportTags"));
            mypage.AddAfterSelf(xNewChild);
            xmlDocument.Save("asd.xml");
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.Message);
        }

将const值206放入代码中,根据需要进行修改

执行后 after


“那可能有用,但我没有在这个项目中使用Linq。大声笑,也许我应该!!!!!”

所以试试这个,你必须在xmlNode的父节点上调用insertAfter

        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.Load("asd.xml");
        try
        {
            string sPath = "//Pages[@PageContentID=\"206\"]";
            var xmlNode = xmlDocument.SelectSingleNode(sPath);

            XmlElement xNewChild = xmlDocument.CreateElement("Pages");
            xNewChild.SetAttribute("Name", "Another New Page");
            xNewChild.SetAttribute("PageContentID", Guid.NewGuid().ToString());
            xNewChild.SetAttribute("Template", "ReportTags");

            xmlNode.ParentNode.InsertAfter(xNewChild, xmlNode);
            xmlDocument.Save("asd.xml");
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.Message);
        }

after