php - 如何使用命名空间创建数组到 SOAPXML?
问题描述
我需要以下格式的输出:
<ns1:CustomerDetails>
<_cd:Name>My Name</_cd:Name>
<_pd:PersonalDetails>
<_bio:Age>20</_bio:Age>
</_pd:PersonalDetails>
<_cd:SomeVar>Var Value</_cd:SomeVar>
</ns1:CustomerDetails>
我可以创建任何格式的数组,例如:
$vars['ns1']['CustomerDetails']['_cd']['Name']="MY Name";
$vars['ns1']['CustomerDetails']['_pd']['PersonalDetails']['_bio']['Age']="20";
$vars['ns1']['CustomerDetails']['_cd']['SomeVars']="Var Value";
我使用了以下代码:
class ArrToXml{
static function parse($arr){
$dom = new DOMDocument('1.0');
self::recursiveParser($dom,$arr,$dom);
return $dom->saveXML();
}
private static function recursiveParser(&$root, $arr, &$dom){
foreach($arr as $key => $item){
if(is_array($item) && !is_numeric($key)){
$node = $dom->createElement($key);
self::recursiveParser($node,$item,$dom);
$root->appendChild($node);
}elseif(is_array($item) && is_numeric($key)){
self::recursiveParser($root,$item,$dom);
}else{
$node = $dom->createElement($key, $item);
$root->appendChild($node);
}
}
}
}
$xmlRequest = ArrToXml::parse($requestArray);
...但我没有得到命名空间值。我应该在代码中做哪些更改以获得我想要的值?
解决方案
数据数组不允许区分命名空间指示符和标签名称。两者都只是钥匙。一种解决方案是使用 QCNames 作为键:
$data = [
'c:CustomerDetails' => [
'cd:Name' => "MY Name",
'pd:PersonalDetails' => [
'bio:Age' => "20"
],
'cd:SomeVars' => "Var Value",
]
];
此外,您还需要指标的命名空间信息:
$xmlns = [
'c' => ['prefix' => 'ns1', 'uri' => 'urn:c'],
'cd' => ['prefix' => '_cd', 'uri' => 'urn:cd'],
'pd' => ['prefix' => '_pd', 'uri' => 'urn:pd'],
'bio' => ['prefix' => '_bio', 'uri' => 'urn:bio']
];
我建议包括一个前缀来解耦代码。
大多数情况下,将数据直接附加到 DOM 是一种更好、更简单的解决方案。我通常为此定义一个接口并在不同的数据和序列化程序类中实现它:
interface XMLAppendable {
public function appendTo(DOMNode $parentNode);
}
数据数组的映射器也可以实现接口。它需要数据数组和有关命名空间的信息。
class ArrayAppender implements XMLAppendable {
private $_data;
private $_xmlns;
public function __construct(array $data, array $xmlns = []) {
$this->_data = $data;
$this->_xmlns = $xmlns;
}
public function appendTo(DOMNode $parentNode) {
$this->appendArrayTo($parentNode, $this->_data);
}
private function appendArrayTo(DOMNode $parentNode, array $data) {
$document = $parentNode instanceof DOMDocument
? $parentNode : $parentNode->ownerDocument;
foreach ($data as $key => $value) {
if (FALSE !== strpos($key, ':')) {
[$prefix, $tagName] = explode(':', $key);
if (isset($this->_xmlns[$prefix])) {
$namespace = $this->_xmlns[$prefix];
} else {
throw new UnexpectedValueException(
'Can not find namespace for '.$prefix
);
}
} else {
$namespace = ['prefix' => '', 'uri' => ''];
$tagName = $key;
}
$parentNode->appendChild(
$child = $document->createElementNS(
$namespace['uri'],
$namespace['prefix'] ? $namespace['prefix'].':'.$tagName : $tagName
)
);
if (is_array($value)) {
$this->appendArrayTo($child, $value);
} else {
$child->textContent = (string)$value;
}
}
}
}
使用演示:
$document = new DOMDocument();
$arrayToXML = new ArrayAppender($data, $xmlns);
$arrayToXML->appendTo($document);
$document->formatOutput = TRUE;
echo $document->saveXML();
输出:
<?xml version="1.0"?>
<ns1:CustomerDetails xmlns:ns1="urn:c">
<_cd:Name xmlns:_cd="urn:cd">MY Name</_cd:Name>
<_pd:PersonalDetails xmlns:_pd="urn:pd">
<_bio:Age xmlns:_bio="urn:bio">20</_bio:Age>
</_pd:PersonalDetails>
<_cd:SomeVars xmlns:_cd="urn:cd">Var Value</_cd:SomeVars>
</ns1:CustomerDetails>
推荐阅读
- css - 页面中的 Ionic 4 SCSS 被忽略
- flutter - 自定义按钮在子小部件上具有默认大写文本
- android - 尝试使用 Firebase 进行电话身份验证时出现 FirebaseAuthInvalidUserException。(ERROR_INVALID_USER_TOKEN)
- hyperledger-fabric - 未能订购交易。错误代码:SERVICE_UNAVAILABLE 使用 raft 共识协议
- java - org.springframework.web.client.HttpClientErrorException: 401 null
- typescript - 如何调试 TypeScript 编译性能问题
- rest - 通过自定义页面的 REST API 从 Tableau Server 获取过滤/聚合的数据
- google-chrome - Chrome 桌面 PWA 多实例开启
- html - div 仅出现在 Chrome 中
- python-3.x - 如何在管道中使用适当的 FunctionTransformer 制作 GridSearchCV?