如何在没有名称空间的情况下将XML字符串附加到DOMDocument

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在没有名称空间的情况下将XML字符串附加到DOMDocument相关的知识,希望对你有一定的参考价值。

我正在使用php并且必须构建一个包含SOAP标记内的XML消息的soap:Body(1.1,Document / Literal)请求。

我的第一个问题是我之前从未使用过这个“协议”。

我的XML消息非常复杂,所以我使用SimpleXMLElement类来单独构建它。要编写SOAP消息,我有两个XML字符串:

1- SOAP结构。

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Header></soap:Header>
  <soap:Body>...</soap:Body>
</soap:Envelope>

2-我的自定义XML字符串

<eSocial xmlns="http://www.esocial.gov.br/schema/lote/eventos/envio/v2_2_02" grupo="1">
  <envioLoteEventos>
    <ideEmpregador tpInsc="1" nrInsc="0000000012"/>
    <ideTransmissor tpInsc="1" nrInsc="0000000012"/>
    <eventos>
      <eSocial xmlns="http://www.esocial.gov.br/schema/evt/evtInfoEmpregador/v2_2_02">
        <evtInfoEmpregador Id="8515">...</evtInfoEmpregador>
      </eSocial>
    </eventos> 
  </envioLoteEventos>
</eSocial>
  • 我需要的是:soap:Body标签内的第二个字符串就像它一样。
  • 我得到的:soap:Body中的第二个字符串,其中有一堆命名空间由DOMDocument自动添加。

我正在使用的算法(不是完整代码):

$soapBodyElement = new SimpleXMLElement($soapBodyString);
$customMessageElement = new SimpleXMLElement($customMessageString);
// Some operations...
$domParent = dom_import_simplexml($soapBodyElement);
$domChild = dom_import_simplexml($customMessageElement);
$domDocument = $domParent->ownerDocument->importNode($domChild, true);
$domParent->appendChild($domDocument);

echo $domParent->ownerDocument->saveXML();

输出:

<soap:Envelope 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Header/>
  <soap:Body>
    <eSocial xmlns="http://www.esocial.gov.br/schema/lote/eventos/envio/v2_2_02" xmlns:default="http://www.esocial.gov.br/schema/evt/evtInfoEmpregador/v2_2_02" xmlns:default1="http://www.w3.org/2000/09/xmldsig#" grupo="1">
      <envioLoteEventos>
        <ideEmpregador tpInsc="1" nrInsc="0000000012"/>
        <ideTransmissor tpInsc="1" nrInsc="0000000012"/>
        <eventos>
          <default:eSocial xmlns="http://www.esocial.gov.br/schema/evt/evtInfoEmpregador/v2_2_02">
            <default:evtInfoEmpregador Id="2550">...</default:evtInfoEmpregador>
          </default:eSocial>
        </eventos>
      </envioLoteEventos>
    </eSocial>     
  </soap:Body>
</soap:Envelope>

老实说,我不知道为什么添加了这个default前缀(名称空间?)。

如何在没有此自动行为的情况下附加两个XML字符串?

答案

您可以使用Marshal XML Serializer,它比DOMDocument和SimpleXML更容易使用。

然后你可以做以下事情:

SoapEnvelopeMapper.php

use KingsonDeMarshalAbstractXmlMapper;

class SoapEnvelopeMapper extends AbstractXmlMapper {

    /**
     * @var AbstractXmlMapper
     */
    private $messageMapper;

    public function __construct(AbstractXmlMapper $messageMapper) {
        $this->messageMapper = $messageMapper;
    }

    public function map($data) {
        return [
            'soap:Envelope' => [
                $this->attributes() => [
                    'xmlns:xsi'  => 'http://www.w3.org/2001/XMLSchema-instance',
                    'xmlns:xsd'  => 'http://www.w3.org/2001/XMLSchema',
                    'xmlns:soap' => 'http://www.w3.org/2003/05/soap-envelope',
                ],
                'soap:Header' => null,
                'soap:Body' => $this->item($this->messageMapper, $data),
            ]
        ];
    }
}

SoapMessageMapper.php

use KingsonDeMarshalAbstractXmlMapper;

class SoapMessageMapper extends AbstractXmlMapper {

    public function map($data) {
        return [
            'eSocial' => [
                $this->attributes() => [
                    'xmlns'          => 'http://www.esocial.gov.br/schema/lote/eventos/envio/v2_2_02',
                    'xmlns:default'  => 'http://www.esocial.gov.br/schema/evt/evtInfoEmpregador/v2_2_02',
                    'xmlns:default1' => 'http://www.w3.org/2000/09/xmldsig#',
                    'grupo'          => 1,
                ],
                'envioLoteEventos' => [
                    'ideEmpregador' => [
                        $this->attributes() => [
                            'tpInsc' => 1,
                            'nrInsc' => '0000000012',
                        ],
                    ],
                    'ideTransmissor' => [
                        $this->attributes() => [
                            'tpInsc' => 1,
                            'nrInsc' => '0000000012',
                        ],
                    ],
                ],
                'eventos' => [
                    'eSocial' => [
                        $this->attributes() => [
                            'xmlns' => 'http://www.esocial.gov.br/schema/evt/evtInfoEmpregador/v2_2_02',
                        ],
                        'evtInfoEmpregador' => [
                            $this->attributes() => [
                                'Id' => 2550,
                            ],
                            $this->data() => '...',
                        ],
                    ],
                ],
            ]
        ];
    }
}

SoapResponse.php

$data = new stdClass();

$messageMapper  = new SoapMessageMapper();
$envelopeMapper = new SoapEnvelopeMapper($messageMapper);

$xml = MarshalXml::serializeItem($envelopeMapper, $data);

以上是关于如何在没有名称空间的情况下将XML字符串附加到DOMDocument的主要内容,如果未能解决你的问题,请参考以下文章

如何在不删除旧文档的情况下将 XMLDocument 附加到 LocalStorage

如何在不导致复制的情况下将 char 数据附加到 std::vector

在没有 CSV 的情况下将 CSV 附加到 Python 中的电子邮件

如何在不跟踪索引的情况下将元素附加到列表中?

Rails - 在没有 <%= %> 的情况下将内容附加到辅助方法的块

有没有办法在不使用通知服务扩展的情况下将图像附加到推送通知?