<item>
<name>item2</name>
<platform>
<platformType>Android</platformType>
<location>url_a</location>
</platform>
<platform>
<platformType>iOS</platformType>
<location>url_b</location>
</platform>
<platform>
<platformType>Windows</platformType>
<location>url_c</location>
</platform>
</item>
这是我的XML代码。 如何将每个项目的platformType放入数组中 比如
Array
(
[0] => Array
(
[platformID] => Android, iOS
)
[1] => Array
(
[platformID] => Android, iOS, Windows
)
)
答案 0 :(得分:0)
您想要使用最复杂的XML php parsers之一。
XMLReader是XML Pull parser:与Document Object Model不同,XMLReader不会立即将整个文档加载到内存中,而是按顺序读取文件。这意味着使用它您无法直接找到特定节点,但您必须先读取XML文件,直到找到所需的节点。
当你必须解析非常大的XML文件时,这是必须的选择,但即使在这些情况下,如果与DOM解析器一起使用也会更加舒适,因为XMLReader在开发方面非常复杂。
在下面的示例中,我将向您展示如何使用纯XMLReader获取阵列,与另外两个漫反射解析器相比:SimpleXML和DOMDocument。 SimpleXML可能是最常用的,它被认为是DOMDocument最高效的。相反,DOMDocument更强大,可定制。 SimpleXML和DOMDocument都支持(有限的)XPath查询系统,允许您简化XML内部的导航。
Here您可以找到几乎所有可用的XML / HTML解析器的详细比较。
请仔细注意:
Stack Overflow不是免费的复制粘贴代码服务。以下示例旨在说明不同的解析器行为。我已根据您的示例使用this XML sample测试了每个示例,但可能您的文档结构更复杂,因此您必须使代码适应它。如果在不同的树位置具有相同的节点名称,则尤其如此。
在以下所有示例中,$result
最终数组是:
Array
(
[0] => Android
[1] => Android, iOS, Windows
)
$xml = new XMLReader(); # Init XMLReader
$xml->open( "file://$filePath" ); # Open XML File
$result = array(); # Init result array
while( $xml->read() ) # Main read loop
{
/* If current node is item, start analyzing it: */
if( $xml->name == 'item' )
{
/* Create additional XMLReader for item node: */
$node = new XMLReader();
/* Load item XML: */
$node->xml( $xml->readOuterXML() );
/* Init $platforms array: */
$platforms = array();
while( $node->read() )
{
/* Continue reading until platformType if found: */
while( $node->read() && $node->name !== 'platformType' );
/* Add platformType value to $platforms array: */
if( $node->readInnerXML() ) $platforms[] = $node->readInnerXML();
/* Continue reading until platformType closing tag if found: */
while( $node->read() && $node->name !== 'platformType' );
}
/* Add imploded $platforms to $result: */
$result[] = implode( ', ', $platforms );
/* Continue reading until item closing tag if found: */
while( $xml->read() && $xml->name !== 'item' );
}
}
如您所见,要构造一个非常简单的数组,我们必须编写大量代码。考虑到这只是一个例子:在现实世界中,您需要使用额外的检查来优化上面的代码,以避免无限循环。如前所述,您可以将XMLReader与DOM解析器结合使用。在此示例中,将$node = new XMLReader()
替换为simplexml_load_string( $xml->readOuterXML() )
是一个好主意。 Here您可以找到使用XMLReader和SimpleXML的详细示例。
$xml = simplexml_load_file( $filepath ); # Load XML File into SimpleXML Object
$result = array(); # Init result array
/* Process each <item> node: */
foreach( $xml->xpath( '//item' ) as $node )
{
$platforms = array();
/* Process each <platform> node: */
foreach( $node->platform as $platform )
{
/* Add platformType value to $platforms array: */
$platforms[] = $platform->platformType[0]->__toString();
}
$result[] = implode( ', ', $platforms );
}
在这个例子中,如下所示,我在与XMLReader示例相同的行中省略了注释。
我使用->xpath
来选择<item>
个节点:在实际的XML示例中没有必要,因为<item>
节点是root的直接子节点(我们可以通过{{1但是,如果$xml->item
节点处于最深位置,则此XPath模式也将起作用。模式开始时的<item>
表示“查找以下模式,无论它在哪里”。
XMLReader的语法更简单:您可以通过//
语法或使用XPath表达式直接转到所需的节点。请注意,->nodeTag
和XPath都返回数组,因此要引用它,您必须使用数组语法(->
)。 SimpleXML总是返回SimpleXMLElement对象,因此要将其用作字符串,您必须使用->platformType[0]
或->__toString()
将其强制转换为字符串。在示例中,您可以省略转换,因为$string = ($string) $platform->platformType[0]
会将对象转换为字符串。
implode()
在阅读了第一个例子后,最后一个例子是自我解释的。您可以注意选择节点的不同语法($dom = New DOMDocument(); # Init DOMDocument Object
$dom->load( $filepath ); # Load XML File into DOMDocument Object
$xpath = new DOMXPath( $dom ); # Init DOMXpath Object
$result = array();
foreach( $xpath->query( '//item' ) as $node )
{
$platforms = array();
/* Process each <platformType> node: */
foreach( $node->getElementsByTagName( 'platformType' ) as $platformType )
{
/* Add platformType value to $platforms array: */
$platforms[] = trim( $platformType->nodeValue );
}
$result[] = implode( ', ', $platforms );
}
和->query
不返回数组,但是DOMNodeList对象:您可以使用{{1}引用每个集合节点} 句法)。此外,您可以使用->getElementsByTagName
检索节点值,而无需进行转换。
现在,您可以选择首选解析器。