Question

I have a .net web application that uses XmlDocument to load an XML String. The format of the XML is as follows:

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

As an example, I am trying to insert a NEW NODE under the 'Chapter' named 'Detailed Results' BETWEEN 'Page' named 'Question List' and 'Answers'. The code I am using to do this is as follows:

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

However, it is not working, my new node is not inserted into the proper place, it is inserted at the top.

Any help would be greatly appreciated!!

Was it helpful?

Solution

Are you sure that xmlNode is returning the node you think it is? Step through it with the debugger.

If it is null, then the node you insert will get added as a child of the DocumentElement as you describe. If it is returning the Pages node, then you should get an exception 'The reference node is not a child of this node'.

This is fairly self explanatory. The code:

doc.DocumentElement.InsertAfter(xNewChild, xmlNode); 

should be:

xmlNode.ParentNode.InsertAfter(xNewChild, xmlNode);

This said, if possible I'd be using XDocument, a part of XLinq. The API's a lot nicer & more powerful, and is generally higher performance. An example:

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

OTHER TIPS

If you don't mind using 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);
        }

It's const value 206 put in the code, modify to your needs

After execution after


"That would probably work, but i am not using Linq for this project. LOL, maybe I should be!!!!!"

So try this, you have to call insertAfter on xmlNode's parent node

        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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top