向XML文档中插入同级节点

4

我有一个使用XmlDocument加载XML字符串的.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>

例如,我想在名称为“Question List”和“Answers”的页面之间,在名为“Detailed Results”的“Chapter”下插入一个新的节点。 我使用的代码如下:
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);
}

然而,它并没有起作用,我的新节点没有插入到正确的位置,而是插入到了顶部。

非常感谢任何帮助!


1
看起来 xmlNode 不是您想要插入的节点 - 请检查您是否使用了正确的节点。 - Jason Williams
实际上,那似乎并不正确。如果我查看xmlNode,它肯定是正确的节点。我相信我的xPath是错误的,但我不知道应该怎么做。 - LilMoke
2个回答

7
你确定xmlNode返回的是你认为的节点吗?请用调试器逐步执行。
如果它是null,那么你插入的节点将作为DocumentElement的子节点添加,就像你所说的一样。如果它返回了Pages节点,则应该会抛出异常“引用节点不是此节点的子节点”。
这相当容易理解。以下代码:
doc.DocumentElement.InsertAfter(xNewChild, xmlNode); 

should be:

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

是的,运行得很好。我的错,我理解了你的评论,非常感谢。 - LilMoke

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);
        }

代码中使用的是常量值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


那可能会起作用,但我在这个项目中没有使用Linq。哈哈,也许我应该用一下!!! - LilMoke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接