PHP/XML -附加片段时默认名称空间的问题



我有原始文件,我想在安全标签中附加片段。

<!-- Original File -->
<example>
<header>
<facticeA>123</facticeA>
<facticeB>456</facticeB>
</header>
<body>
<facticeC>789</facticeC>
</body>
<security></security>
</example>
<!-- ------------ -->
<!-- Original Fragment -->
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_eb0b47cc-d4b0-44ba-a08c-90047e3a8b03" IssueInstant="2022-07-18T14:08:46.138Z" Version="2.0">
<saml2:Issuer></saml2:Issuer>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">XXXXXXXX</Signature>
</saml2:Assertion>
<!-- ----------------- -->

我使用">createDocumentFragment()";和">appendXml ()";PHP函数我得到了这个结果

<!-- Final File -->
<example>
<header>
<facticeA>123</facticeA>
<facticeB>456</facticeB>
</header>
<body>
<facticeC>789</facticeC>
</body>
<security>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:default="http://www.w3.org/2000/09/xmldsig#" ID="_eb0b47cc-d4b0-44ba-a08c-90047e3a8b03" IssueInstant="2022-07-18T14:08:46.138Z" Version="2.0">
<saml2:Issuer/>
<default:Signature xmlns="http://www.w3.org/2000/09/xmldsig#">XXXXXXXX</default:Signature>
</saml2:Assertion>
</security>
</example>
<!-- ---------- -->

插入的片段与原始片段不相同。">";默认:Signature";标签。命名空间"xmldsig"在"签名"标签中添加"断言"标签,并使用word ">default">

如果我删除命名空间"xmldsig"在签名标签我没有问题。插入的片段与原片段相同。

这似乎是节点导入中的一个错误。一个可能的解决方法是在文档元素上为这个名称空间定义一个前缀。

$document = new DOMDocument();
$document->preserveWhiteSpace = false;
$document->loadXML($exampleXML);
$xpath = new DOMXpath($document);
$document->documentElement->setAttributeNS(
'http://www.w3.org/2000/xmlns/', 'xmlns:sig', 'http://www.w3.org/2000/09/xmldsig#'
);
$fragment = $document->createDocumentFragment();
$fragment->appendXML($samlXML);
foreach ($xpath->evaluate('(//security)[1]') as $security) {
$security->appendChild($fragment);
}
$document->formatOutput = true;
echo $document->saveXML();

输出:

<?xml version="1.0"?>
<example xmlns:sig="http://www.w3.org/2000/09/xmldsig#">
<header>
<facticeA>123</facticeA>
<facticeB>456</facticeB>
</header>
<body>
<facticeC>789</facticeC>
</body>
<security>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_eb0b47cc-d4b0-44ba-a08c-90047e3a8b03" IssueInstant="2022-07-18T14:08:46.138Z" Version="2.0">
<saml2:Issuer/>
<sig:Signature xmlns="http://www.w3.org/2000/09/xmldsig#">XXXXXXXX</sig:Signature>
</saml2:Assertion>
</security>
</example>
有趣的是,如果您使用DOM方法创建节点,它可以正常工作:

$document = new DOMDocument();
$document->preserveWhiteSpace = false;
$document->loadXML($exampleXML);
$xpath = new DOMXpath($document);
foreach ($xpath->evaluate('(//security)[1]') as $security) {
$security->appendChild(
$saml = $document->createElementNS('urn:oasis:names:tc:SAML:2.0:assertion', 'saml2:Assertion')
);
$saml->setAttribute('ID', '_eb0b47cc-d4b0-44ba-a08c-90047e3a8b03');
$saml->appendChild(
$document->createElementNS('urn:oasis:names:tc:SAML:2.0:assertion', 'saml2:Issuer')
);
$saml->appendChild(
$signature = $document->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'Signature')
);
$signature->textContent = 'XXXXXXXX';
}
$document->formatOutput = true;
echo $document->saveXML();

输出:

<?xml version="1.0"?>
<example>
<header>
<facticeA>123</facticeA>
<facticeB>456</facticeB>
</header>
<body>
<facticeC>789</facticeC>
</body>
<security>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_eb0b47cc-d4b0-44ba-a08c-90047e3a8b03">
<saml2:Issuer/>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">XXXXXXXX</Signature>
</saml2:Assertion>
</security>
</example>

您可以创建一个递归函数,从片段中重新创建节点。

最新更新