Вставить узел в XML-документ с помощью С#

Я пытался вставить узел XML в документ XML в определенной позиции.

Это мой 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>

И я пытаюсь вставить еще один тег <productGroups>0093</productGroups> ниже тега <productGroups>0085</productGroups>

Ожидается, как показано ниже:

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

Для его достижения использовался приведенный ниже код С#.

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

И он возвращает значение, например

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

Я новичок в коде C #, пожалуйста, помогите мне получить XML-документ, как и ожидалось. ваша помощь очень ценится.


person Madhan    schedule 19.08.2015    source источник
comment
Не могли бы вы конкретно указать, что не так с вашим выводом, то есть как он не соответствует тому, что вы ищете? Пожалуйста, не заставляйте нас просматривать ваш XML, чтобы попытаться выяснить, что с ним не так.   -  person rory.ap    schedule 19.08.2015
comment
Он просто добавил новый элемент в верхний узел документа. Вам нужно перейти к узлу, к которому вы хотите его добавить — в вашем случае к узлу ‹readContract›.   -  person user2867342    schedule 19.08.2015
comment
Используйте запрос XPath, например XmlNode titleNode = doc.SelectSingleNode("//Envelope/Body/readContract");   -  person user2867342    schedule 19.08.2015


Ответы (3)


Когда вы делаете это:

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

Вы добавляете узел в корень документа. Вероятно, вы хотели выбрать фактический узел readContract, к которому должен быть добавлен элемент. Например:

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

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

Конечно, вы, вероятно, захотите обработать случай, когда уже есть несколько дочерних элементов productGroup, но идея та же.

person theB    schedule 19.08.2015

Похоже, проблема связана с пространствами имен. Это сработало для меня:

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

Или, если вам не нравятся пространства имен, как мне, вы можете попробовать немного более «грубый» подход:

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

Его можно оптимизировать, но я думаю, что это помогает подчеркнуть, что основной причиной являются разные пространства имен в документе.

person Volkan Paksoy    schedule 19.08.2015

Вы можете использовать метод XmlNode.InsertAfter.

public virtual XmlNode InsertAfter(
    XmlNode newChild,
    XmlNode refChild
)

Где

newChild = The XmlNode to insert

а также

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

Пожалуйста, проверьте эта ссылка для получения информации.

И проверьте эту ссылку с ответом на SO.

P.S.
Всегда проверяйте другие ответы перед публикацией нового вопроса.

person ManishChristian    schedule 19.08.2015