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

XmlDocument创建仅含命名空间前缀元素的问题(X++/.NET)

问题:如何在X++中生成不带重复命名空间声明的带前缀XML标签

我需要生成如下结构的XML(根标签为<CBIBdyPaymentRequest>),要求<PMRQ:GrpHdr>仅保留PMRQ前缀,不要附加xmlns:PMRQ="urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01"属性:

<?xml version="1.0" encoding="UTF-8"?>
<CBIBdyPaymentRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01 CBIBdyPaymentRequest.00.04.01.xsd" xmlns:PMRQ="urn:CBI:xsd:CBIPaymentRequest.00.04.01" xmlns="urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01">
  <CBIEnvelPaymentRequest>
    <CBIPaymentRequest>
      <PMRQ:GrpHdr>

但当前用X++生成的XML里,<PMRQ:GrpHdr>和<PMRQ:PmtInf>自动带上了额外的命名空间声明,而它们的子标签却没有这个问题:

<?xml version="1.0" encoding="UTF-8"?>
<CBIBdyPaymentRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01 CBIBdyPaymentRequest.00.04.01.xsd" xmlns:PMRQ="urn:CBI:xsd:CBIPaymentRequest.00.04.01" xmlns="urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01">
  <CBIEnvelPaymentRequest>
    <CBIPaymentRequest>
      <PMRQ:GrpHdr xmlns:PMRQ="urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01">
        <PMRQ:MsgId>G182581</PMRQ:MsgId>  
        [...] 
      </PMRQ:GrpHdr>
      <PMRQ:PmtInf xmlns:PMRQ="urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01">
        <PMRQ:PmtMtd>TRF</PMRQ:PmtMtd>
      </PMRQ:PmtInf>
    </CBIPaymentRequest>
  </CBIEnvelPaymentRequest>
</CBIBdyPaymentRequest>

我的测试代码如下:

xmlDoc = new XmlDocument();
xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml", 'version="1.0" encoding="UTF-8"'));

nodeRoot = xmlDoc.appendChild(xmlDoc.createElement('CBIBdyPaymentRequest'));

//1. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 属性
nodeRoot.setAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");

//2. xsi:schemaLocation 属性
schemaLocationAttribute = xmlDoc.createAttribute2("xsi:schemaLocation", "http://www.w3.org/2001/XMLSchema-instance");
schemaLocationAttribute.value('urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01 CBIBdyPaymentRequest.00.04.01.xsd');
nodeRoot.setAttributeNode(schemaLocationAttribute);

//3. xmlns:PMRQ="urn:CBI:xsd:CBIPaymentRequest.00.04.01" 属性
nodeRoot.setAttribute("xmlns:PMRQ","urn:CBI:xsd:CBIPaymentRequest.00.04.01");

//4. 默认命名空间 xmlns="urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01"
nodeRoot.setAttribute("xmlns","urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01");

nodeRoot2 = nodeRoot.appendChild(xmlDoc.createElement('CBIEnvelPaymentRequest'));
nodeRoot3 = nodeRoot2.appendChild(xmlDoc.createElement('CBIPaymentRequest'));
nodeRoot3.prefix("PMRQ");

nodeGrpHdr = nodeRoot3.appendChild(xmlDoc.createElement3("PMRQ", "GrpHdr","urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01"));

//msgId
xeTmp = nodeGrpHdr.appendChild(xmlDoc.createElement3("PMRQ","MsgId","urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01"));
xeTmp.appendChild(xmlDoc.createTextNode("test string"));

xeTmp = nodeGrpHdr.appendChild(xmlDoc.createElement3("PMRQ","Tmp","urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01"));
xeTmp.appendChild(xmlDoc.createTextNode("test string"));

nodeGrpHdr2 = nodeRoot3.appendChild(xmlDoc.createElement3("PMRQ", "GrpHdr2","urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01"));
xeTmp = nodeGrpHdr2.appendChild(xmlDoc.createElement3("PMRQ","MsgId2","urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01"));
xeTmp.appendChild(xmlDoc.createTextNode("test string"));

为什么用相同的创建方法,<PMRQ:GrpHdr>会带上额外的命名空间声明,而其子标签不会?如何让<PMRQ:GrpHdr>只保留前缀,不附加该属性?


解答

问题原因

你在根节点声明的PMRQ命名空间是urn:CBI:xsd:CBIPaymentRequest.00.04.01,但创建<PMRQ:GrpHdr>等标签时,传入的命名空间却是urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01(和根节点的默认命名空间一致)。XML解析器发现当前标签使用的PMRQ前缀对应的命名空间,和上级节点声明的PMRQ命名空间不匹配,就会自动在当前标签上重新声明这个前缀对应的新命名空间。

而子标签(比如<PMRQ:MsgId>)之所以没有额外声明,是因为它们继承了父标签<PMRQ:GrpHdr>上重新声明的命名空间,不需要再重复添加。

解决方案

创建PMRQ前缀的标签时,使用和根节点一致的PMRQ命名空间值,也就是urn:CBI:xsd:CBIPaymentRequest.00.04.01,替换掉代码中createElement3的第三个参数。

修改后的关键代码片段:

// 使用根节点声明的PMRQ命名空间
nodeGrpHdr = nodeRoot3.appendChild(xmlDoc.createElement3("PMRQ", "GrpHdr","urn:CBI:xsd:CBIPaymentRequest.00.04.01"));

//msgId
xeTmp = nodeGrpHdr.appendChild(xmlDoc.createElement3("PMRQ","MsgId","urn:CBI:xsd:CBIPaymentRequest.00.04.01"));
xeTmp.appendChild(xmlDoc.createTextNode("test string"));

xeTmp = nodeGrpHdr.appendChild(xmlDoc.createElement3("PMRQ","Tmp","urn:CBI:xsd:CBIPaymentRequest.00.04.01"));
xeTmp.appendChild(xmlDoc.createTextNode("test string"));

nodeGrpHdr2 = nodeRoot3.appendChild(xmlDoc.createElement3("PMRQ", "GrpHdr2","urn:CBI:xsd:CBIPaymentRequest.00.04.01"));
xeTmp = nodeGrpHdr2.appendChild(xmlDoc.createElement3("PMRQ","MsgId2","urn:CBI:xsd:CBIPaymentRequest.00.04.01"));
xeTmp.appendChild(xmlDoc.createTextNode("test string"));

修改后生成的XML

<?xml version="1.0" encoding="UTF-8"?>
<CBIBdyPaymentRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01 CBIBdyPaymentRequest.00.04.01.xsd" xmlns:PMRQ="urn:CBI:xsd:CBIPaymentRequest.00.04.01" xmlns="urn:CBI:xsd:CBIBdyPaymentRequest.00.04.01">
    <CBIEnvelPaymentRequest>
        <CBIPaymentRequest>
            <PMRQ:GrpHdr>
                <PMRQ:MsgId>test string</PMRQ:MsgId>
                <PMRQ:Tmp>test string</PMRQ:Tmp>
            </PMRQ:GrpHdr>
            <PMRQ:GrpHdr2>
                <PMRQ:MsgId2>test string</PMRQ:MsgId2>
            </PMRQ:GrpHdr2>
        </CBIPaymentRequest>
    </CBIEnvelPaymentRequest>
</CBIBdyPaymentRequest>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 01:24:50