You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

合并XML文档至SOAP信封时遇System.ArgumentException问题求助

问题描述

我们使用的API允许<Transaction>标签下包含多个<Message>及其他配置项。<Message>标签及其子节点是随任务变化的部分,因此将其独立存放在XmlDocument中,尝试合并回SOAP信封的<Transaction>节点时,调用AppendChild方法抛出异常:

System.ArgumentException: 'The node to be inserted is from a different document context.'

相关代码

生成SOAP信封的代码

public XmlDocument SoapRequestEnvelope()
{
    XmlDocument envelope = new XmlDocument();
    envelope.LoadXml(@"\n        &lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\n        &lt;soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:tyl=\"http://www.VendorWeb.com\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"&gt;\n            &lt;soap:Header&gt;\n                &lt;wsa:To&gt;https://test.VendorAccess.cloud/ExternalWebService/TranslationBridgeExternalService.asmx&lt;/wsa:To&gt;\n                &lt;wsa:Action&gt;http://www.MyVendor.com/VendorApiTxnExecutionSyncXml&lt;/wsa:Action&gt;\n                &lt;wsse:Security soap:mustUnderstand=\"1\"&gt;\n                    &lt;wsu:Timestamp wsu:Id =\"Timestamp -Redacted\"&gt;\n                    &lt;wsu:Created&gt;2018-01-10T00:00:00Z&lt;/wsu:Created&gt;\n                    &lt;wsu:Expires&gt;2023-03-31T23:59:59Z&lt;/wsu:Expires&gt;\n                    &lt;/wsu:Timestamp&gt;\n                    &lt;wsse:UsernameToken wsu:Id=\"SecurityToken-Redacted\"&gt;\n                    &lt;wsse:Username&gt;UserName&lt;/wsse:Username&gt;\n                    &lt;wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\"&gt;PASSWORD&lt;/wsse:Password&gt;\n                    &lt;/wsse:UsernameToken&gt;\n                &lt;/wsse:Security&gt;\n                &lt;tyl:ApiMessageContext&gt;\n                    &lt;tyl:SystemEnvironment&gt;MySiteTest&lt;/tyl:SystemEnvironment&gt;\n                    &lt;tyl:RetryCount&gt; 0 &lt;/tyl:RetryCount&gt;\n                    &lt;tyl:AllowFaults&gt; true &lt;/tyl:AllowFaults&gt;\n                &lt;/tyl:ApiMessageContext&gt;\n            &lt;/soap:Header&gt;\n            &lt;soap:Body&gt;\n                &lt;tyl:ApiTxnExecutionSyncXml&gt;\n                    &lt;tyl:apiMessageData&gt;\n                        &lt;Transaction ReferenceNumber=\"IKJT1\" Source=\"IKJT\" TransactionType=\"IKJTEx\" &gt;\n                            &lt;Message MessageType=\"FindCase\" NodeID=\"12\" ReferenceNumber=\"R-19293\" UserID=\"5235126\" Source=\"Vendor\"&gt;\n                                &lt;Options&gt;\n                                    &lt;Nodes&gt;\n                                        &lt;All&gt;True&lt;/All&gt;\n                                    &lt;/Nodes&gt;\n                                    &lt;CaseCategories&gt;\n                                        &lt;All&gt;True&lt;/All&gt;\n                                    &lt;/CaseCategories&gt;\n                                    &lt;CaseTypes&gt;\n                                        &lt;All&gt;True&lt;/All&gt;\n                                    &lt;/CaseTypes&gt;\n                                &lt;/Options&gt;\n                                &lt;SearchCriteria&gt;\n                                    &lt;Case&gt;\n                                        &lt;CaseNumber&gt;123456&lt;/CaseNumber&gt;\n                                    &lt;/Case&gt;\n                                &lt;/SearchCriteria&gt;\n                            &lt;/Message&gt;\n                        &lt;/Transaction&gt;\n                    &lt;/tyl:apiMessageData&gt;\n                &lt;/tyl:ApiTxnExecutionSyncXml&gt;\n            &lt;/soap:Body&gt;\n        &lt;/soap:Envelope&gt;\n    ");
    
    return envelope;
}

生成独立Message的代码

public XmlDocument SOAPReqBody()
{
    XmlDocument body = new XmlDocument();
    body.LoadXml(
        @"&lt;Message MessageType=\"Config\"&gt;\n            &lt;Options&gt;\n                &lt;Nodes&gt;\n                    &lt;All&gt;True&lt;/All&gt;\n                &lt;/Nodes&gt;\n            &lt;/Options&gt;\n            &lt;SearchCriteria&gt;\n                &lt;Case&gt;\n                    &lt;CaseNumber&gt;125487&lt;/CaseNumber&gt;\n                &lt;/Case&gt;\n            &lt;/SearchCriteria&gt;\n        &lt;/Message&gt;"
    );

    return body;
}

原合并代码

public XmlDocument CallXML()
{
    XmlDocument envelope = SoapRequestEnvelope();
    XmlDocument body = SOAPReqBody();
    XmlNode bodyNode = body.DocumentElement;
    XmlNode envelopeNode = envelope.SelectSingleNode("descendant::Transaction");
    XmlElement root = envelope.DocumentElement;

    Console.WriteLine(envelopeNode);
    envelopeNode.AppendChild(bodyNode);

    return (envelope);
}
错误原因

异常的核心是:不同XmlDocument实例的节点无法直接操作。bodyNode属于SOAPReqBody()创建的文档实例,envelopeNode属于SoapRequestEnvelope()创建的另一个文档实例,二者上下文不匹配,直接调用AppendChild会触发异常。

解决方案

使用XmlDocument.ImportNode()方法将外部节点导入到目标文档的上下文,该方法会创建一个适配当前文档的节点副本,之后即可正常添加到目标节点下。

针对长期目标(将信封XML移至外部文件加载),只需将envelope.LoadXml()替换为envelope.Load("路径/信封文件.xml")即可,合并逻辑无需修改。

修改后的合并代码

public XmlDocument CallXML()
{
    XmlDocument envelope = SoapRequestEnvelope();
    XmlDocument body = SOAPReqBody();
    XmlNode bodyNode = body.DocumentElement;
    XmlNode envelopeNode = envelope.SelectSingleNode("descendant::Transaction");

    // 关键步骤:导入外部节点到当前文档上下文,第二个参数true表示递归导入所有子节点
    XmlNode importedNode = envelope.ImportNode(bodyNode, true);
    envelopeNode.AppendChild(importedNode);

    return envelope;
}

添加多个Message节点的示例

如果需要添加多个<Message>,重复执行导入-添加流程即可:

public XmlDocument CallXMLWithMultipleMessages()
{
    XmlDocument envelope = SoapRequestEnvelope();
    XmlNode transactionNode = envelope.SelectSingleNode("descendant::Transaction");

    // 添加第一个Message
    XmlDocument msg1Doc = SOAPReqBody();
    XmlNode importedMsg1 = envelope.ImportNode(msg1Doc.DocumentElement, true);
    transactionNode.AppendChild(importedMsg1);

    // 添加第二个Message(假设有另一个生成Message的方法)
    XmlDocument msg2Doc = GetAnotherMessage();
    XmlNode importedMsg2 = envelope.ImportNode(msg2Doc.DocumentElement, true);
    transactionNode.AppendChild(importedMsg2);

    return envelope;
}

// 示例:生成另一个Message的方法
public XmlDocument GetAnotherMessage()
{
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(@"&lt;Message MessageType=\"UpdateCase\"&gt;\n            &lt;CaseData&gt;\n                &lt;CaseNumber&gt;765432&lt;/CaseNumber&gt;\n                &lt;Status&gt;Closed&lt;/Status&gt;\n            &lt;/CaseData&gt;\n        &lt;/Message&gt;");
    return doc;
}

内容的提问来源于stack exchange,提问作者BenStark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 04:16:59