我有一个基于此功能的方法: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
标记在其出现的所有内容中都丢失了值value
的属性40
。我根本无法理解为什么我的修改版本会发生这种情况,而不是原始代码。
答案 0 :(得分:1)
问题是(必须承认我并不完全理解代码的细节)......
这里的代码......
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)) {