我有一个基于此函数的方法:https://github.com/gaarf/XML-string-to-PHP-array/blob/master/xmlstr_to_array.php
现在我修改了它以满足我的需要,现在看起来是这样的:
private function parseXml($xmlString)
{
$doc = new \DOMDocument;
$doc->loadXML($xmlString);
$root = $doc->documentElement;
$output[$root->tagName] = $this->domnodeToArray($root);
return $output;
}
/**
* @param $node
* @return array|string
*/
private function domNodeToArray($node)
{
$output = [];
switch ($node->nodeType)
{
case XML_CDATA_SECTION_NODE:
case XML_TEXT_NODE:
$output = trim($node->textContent);
break;
case XML_ELEMENT_NODE:
for ($i = 0, $m = $node->childNodes->length; $i < $m; $i++)
{
$child = $node->childNodes->item($i);
$v = $this->domNodeToArray($child);
if (isset($child->tagName))
{
$t = $child->tagName;
if (!isset($output['value'][$t]))
{
$output['value'][$t] = [];
}
$output['value'][$t][] = $v;
}
else if ($v || $v === '0')
{
$output['value'] = (string)$v;
}
}
if (isset($output['value']) && $node->attributes->length && !is_array($output['value']))
{
$output = ['value' => $output['value']];
}
if (!$node->attributes->length && isset($output['value']) && !is_array($output['value']))
{
$output = ['attributes' => [], 'value' => $output['value']];
}
if (isset($output['value']) && is_array($output['value']))
{
if ($node->attributes->length)
{
$a = [];
foreach ($node->attributes as $attrName => $attrNode)
{
$a[$attrName] = (string)$attrNode->value;
}
$output['attributes'] = $a;
}
else
{
$output['attributes'] = [];
}
foreach ($output['value'] as $t => $v)
{
if (is_array($v) && count($v) == 1 && $t != 'attributes')
{
$output['value'][$t] = $v[0];
}
}
}
break;
}
return $output;
}
使用示例XML/XSD字符串,并尝试使用上面的方法(parseXML
)将其转换为数组,将导致丢失一些属性,,但只有当使用我的更改版本时,它可以与github存储库中提供的方法一起正常工作。
示例XSD字符串如下所示:
$xsdStr = '<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="book">
<xs:complexType>
<xs:sequence>
<xs:element name="title">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="40"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="author">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="40"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="character" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="name">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="40"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="friend-of" maxOccurs="unbounded" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="40"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="since" type="xs:date"/>
<xs:element name="qualification" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="isbn" use="required">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:totalDigits value="10"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>';
echo '<pre>';
echo print_r($this->parseXml($xsdStr), true);
此数组的输出将如下所示(print_r
):https://pastebin.com/sYvf5Z4X (使用URL,因为它将超过字符限制)。
为了方便起见,maxLength
标记在所有出现的标记中都会丢失其值为40
的属性value
。我只是不明白为什么我的修改后的版本会发生这种情况,而不是原始代码。
发布于 2018-04-19 21:52:04
问题是(必须承认我并不完全理解代码的细节)……
在这里的代码中..。
if (isset($output['value']) && is_array($output['value']))
{
if ($node->attributes->length)
仅当为节点设置了值时,此操作才有效。我认为发生的情况是任何叶节点都没有值,因此跳过属性值。
if ($node->attributes->length)
{
// ...
}
if (isset($output['value']) && is_array($output['value']))
如果将属性检查移到此分支之外,则可以正常工作。
不同的是,原始代码不检查是否设置了值,它只检查是否存在某些东西(原始代码的第48行)……
if(is_array($output)) {
https://stackoverflow.com/questions/49922294
复制相似问题