Insert node in xml document using c#

2020-04-20 15:40发布

问题:

I was trying to insert an XML node in XML document at a specific position.

This is my xml:

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
    <Body>
        <readContract xmlns="http://implementation.company.schema.reference">
            <ContactNumbers>10158</ContactNumbers>
            <productGroups>0085</productGroups>
            <indicationBalanceInfo>false</indicationBalanceInfo>
            <indicationBlocked>true</indicationBlocked>
        </readContract>
    </Body>
</Envelope>

And am trying to insert another tag <productGroups>0093</productGroups> below to the tag <productGroups>0085</productGroups>

Expecting like the below:

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
    <Body>
        <readContract xmlns="http://implementation.company.schema.reference">
            <ContactNumbers>10158</ContactNumbers>
            <productGroups>0085</productGroups>
            <productGroups>0093</productGroups>
            <indicationBalanceInfo>false</indicationBalanceInfo>
            <indicationBlocked>true</indicationBlocked>
        </readContract>
    </Body>
</Envelope>

Used the below C# code to achieve it.

XmlDocument doc = new XmlDocument();
string inputxml = this.StServiceCallActivity5.InputEnvelope.InnerXml.ToString();
//Here inputxml contains whole xml document.
string addxml = "<productGroups>0093</productGroups>";
doc.LoadXml(inputxml);
XmlDocumentFragment xmlDocFrag = doc.CreateDocumentFragment();
xmlDocFrag.InnerXml = addxml;
XmlElement parentEle = doc.DocumentElement;
parentEle.AppendChild(xmlDocFrag);

And it returns value like

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
    <Body>
        <readContract xmlns="http://implementation.company.schema.reference">
            <ContactNumbers>10158</ContactNumbers>
            <productGroups>0085</productGroups>
            <productGroups>0093</productGroups>
            <indicationBalanceInfo>false</indicationBalanceInfo>
            <indicationBlocked>true</indicationBlocked>
        </readContract>
    </Body>
    <productGroups xmlns="">0093</productGroups>
</Envelope>

Am a newbie to C# code, kindly help me to get the XML doc as expected. your help is much appreciated.

回答1:

When you do this:

XmlElement parentEle = doc.DocumentElement;
parentEle.AppendChild(xmlDocFrag);

You're appending the node to the root of the document. You probably wanted to select the actual readContract node that the item is supposed to be appended into. As an example:

XmlNode newNode = doc.CreateNode(XmlNodeType.Element, "productGroup", "");
newNode.InnerText = "something";

XmlNode readContractNode = doc["Envelope"]["Body"]["readContract"];
XmlElement groups = readContractNode["productGroups"];
readContractNode.InsertAfter(newNode, groups);

Of course you'd probably want to handle the case where there are already multiple child productGroup elements, but the idea is the same.



回答2:

Looks like namespaces are causing the problem. This worked for me:

XmlDocument doc = new XmlDocument();
doc.LoadXml(File.ReadAllText("XMLFile1.xml"));
XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("ns1", "http://schemas.xmlsoap.org/soap/envelope/");
ns.AddNamespace("ns2", "http://implementation.company.schema.reference");
var rootNode = doc.SelectSingleNode("//ns1:Envelope", ns);
var readContractNode = rootNode.FirstChild.FirstChild;
var newNode = doc.CreateNode(XmlNodeType.Element, "productGroups", "http://implementation.company.schema.reference");
newNode.InnerText = "0093";
readContractNode.InsertAfter(newNode, readContractNode.SelectSingleNode("//ns2:productGroups", ns));

Or if you don't fancy namespaces like I me, you can try a bit more "brute-forcy" approach:

XmlDocument doc = new XmlDocument();
doc.LoadXml(File.ReadAllText("XMLFile1.xml"));
var newNode = doc.CreateNode(XmlNodeType.Element, "productGroups", "http://implementation.company.schema.reference");
newNode.InnerText = "0093";
doc.FirstChild.FirstChild.FirstChild.InsertAfter(newNode, doc.FirstChild.FirstChild.FirstChild.FirstChild.NextSibling);

It can be optimized but I think it helps to make the point that root cause is the different namespaces in the document.



回答3:

You may want to use XmlNode.InsertAfter Method.

public virtual XmlNode InsertAfter(
    XmlNode newChild,
    XmlNode refChild
)

Where

newChild = The XmlNode to insert

and

refChild = The XmlNode that is the reference node. The newNode is placed after the refNode

Please check this link for information.

And check this link with answer on SO.

P.S.
Always check other answers before posting new question.



标签: c# xml hp-uft