У меня есть несколько узлов просмотра, возвращенных из API Amazon в виде XML, который выглядит как вывод ниже. Как я могу пройти через этот беспорядок / сгладить его и извлечь нужные мне данные. Это вход:
object(SimpleXMLElement)#72 (1) {
["BrowseNode"]=>
array(2) {
[0]=>
object(SimpleXMLElement)#73 (3) {
["BrowseNodeId"]=>
string(10) "1342630031"["Name"]=>
string(8) "Chargers"["Ancestors"]=>
object(SimpleXMLElement)#75 (1) {
["BrowseNode"]=>
object(SimpleXMLElement)#76 (3) {
["BrowseNodeId"]=>
string(9) "389516011"["Name"]=>
string(11) "Accessories"["Ancestors"]=>
object(SimpleXMLElement)#77 (1) {
["BrowseNode"]=>
object(SimpleXMLElement)#78 (3) {
["BrowseNodeId"]=>
string(9) "389514011"["Name"]=>
string(38) "Sat Nav, GPS, Navigation & Accessories"["Ancestors"]=>
object(SimpleXMLElement)#79 (1) {
["BrowseNode"]=>
object(SimpleXMLElement)#80 (4) {
["BrowseNodeId"]=>
string(6) "560800"["Name"]=>
string(10) "Categories"["IsCategoryRoot"]=>
string(1) "1"["Ancestors"]=>
object(SimpleXMLElement)#81 (1) {
["BrowseNode"]=>
object(SimpleXMLElement)#82 (2) {
["BrowseNodeId"]=>
string(6) "560798"["Name"]=>
string(19) "Electronics & Photo"}
}
}
}
}
}
}
}
}
[1]=>
object(SimpleXMLElement)#74 (3) {
["BrowseNodeId"]=>
string(9) "340328031"["Name"]=>
string(12) "Car Chargers"["Ancestors"]=>
object(SimpleXMLElement)#75 (1) {
["BrowseNode"]=>
object(SimpleXMLElement)#76 (3) {
["BrowseNodeId"]=>
string(9) "340327031"["Name"]=>
string(8) "Chargers"["Ancestors"]=>
object(SimpleXMLElement)#77 (1) {
["BrowseNode"]=>
object(SimpleXMLElement)#78 (3) {
["BrowseNodeId"]=>
string(6) "560826"["Name"]=>
string(11) "Accessories"["Ancestors"]=>
object(SimpleXMLElement)#79 (1) {
["BrowseNode"]=>
object(SimpleXMLElement)#80 (3) {
["BrowseNodeId"]=>
string(10) "1340509031"["Name"]=>
string(29) "Mobile Phones & Communication"["Ancestors"]=>
object(SimpleXMLElement)#81 (1) {
["BrowseNode"]=>
object(SimpleXMLElement)#82 (4) {
["BrowseNodeId"]=>
string(6) "560800"["Name"]=>
string(10) "Categories"["IsCategoryRoot"]=>
string(1) "1"["Ancestors"]=>
object(SimpleXMLElement)#83 (1) {
["BrowseNode"]=>
object(SimpleXMLElement)#84 (2) {
["BrowseNodeId"]=>
string(6) "560798"["Name"]=>
string(19) "Electronics & Photo"}
}
}
}
}
}
}
}
}
}
}
}
}
Я хочу пройти через это и сплющить его в структуру, с которой я могу работать следующим образом:
array(
(1342630031,'Chargers'),
(389516011,'Accessories'),
(389514011,'Sat Nav, GPS, Navigation & Accessories'),
(560800,'Categories'),
(560798,'Electronics & Photo'),
(340328031,'Car Chargers'),
(340327031,'Chargers'),
(560826,'Accessories'),
(1340509031,'Mobile Phones & Communication'),
(560800,'Categories'),
(560798,'Electronics & Photo')
)
Это позволило бы мне:
echo $ array [0] [0];
echo $ array [0] [1];
echo $ array [5] [1];
Что бы дать:
1342630031
Зарядные устройства
электроника & Фото
так далее…
Если это поможет, вот оригинальный XML
<?xml version="1.0" encoding="UTF-8"?>
<BrowseNodes>
<BrowseNode>
<BrowseNodeId>1342630031</BrowseNodeId>
<Name>Chargers</Name>
<Ancestors>
<BrowseNode>
<BrowseNodeId>389516011</BrowseNodeId>
<Name>Accessories</Name>
<Ancestors>
<BrowseNode>
<BrowseNodeId>389514011</BrowseNodeId>
<Name>Sat Nav, GPS, Navigation & Accessories</Name>
<Ancestors>
<BrowseNode>
<BrowseNodeId>560800</BrowseNodeId>
<Name>Categories</Name>
<IsCategoryRoot>1</IsCategoryRoot>
<Ancestors>
<BrowseNode>
<BrowseNodeId>560798</BrowseNodeId>
<Name>Electronics & Photo</Name>
</BrowseNode>
</Ancestors>
</BrowseNode>
</Ancestors>
</BrowseNode>
</Ancestors>
</BrowseNode>
</Ancestors>
</BrowseNode>
<BrowseNode>
<BrowseNodeId>340328031</BrowseNodeId>
<Name>Car Chargers</Name>
<Ancestors>
<BrowseNode>
<BrowseNodeId>340327031</BrowseNodeId>
<Name>Chargers</Name>
<Ancestors>
<BrowseNode>
<BrowseNodeId>560826</BrowseNodeId>
<Name>Accessories</Name>
<Ancestors>
<BrowseNode>
<BrowseNodeId>1340509031</BrowseNodeId>
<Name>Mobile Phones & Communication</Name>
<Ancestors>
<BrowseNode>
<BrowseNodeId>560800</BrowseNodeId>
<Name>Categories</Name>
<IsCategoryRoot>1</IsCategoryRoot>
<Ancestors>
<BrowseNode>
<BrowseNodeId>560798</BrowseNodeId>
<Name>Electronics & Photo</Name>
</BrowseNode>
</Ancestors>
</BrowseNode>
</Ancestors>
</BrowseNode>
</Ancestors>
</BrowseNode>
</Ancestors>
</BrowseNode>
</Ancestors>
</BrowseNode>
</BrowseNodes>
Использование Xpath — это самый простой способ считывания данных из XML-документа. Вы используете одно выражение для итерации элементов и несколько для извлечения данных для каждого элемента.
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$result = [];
foreach($xpath->evaluate('//BrowseNode[BrowseNodeId]') as $browseNode) {
$id = $xpath->evaluate('string(BrowseNodeId)', $browseNode);
if (array_key_exists($id, $result)) {
continue;
}
$result[$id] = [
'id' => $id,
'name' => $xpath->evaluate('string(Name)', $browseNode)
];
}
var_dump($result);
Выход:
array(9) {
[1342630031]=>
array(2) {
["id"]=>
string(10) "1342630031"["name"]=>
string(8) "Chargers"}
[389516011]=>
array(2) {
["id"]=>
string(9) "389516011"["name"]=>
string(11) "Accessories"}
...
}
//BrowseNode[BrowseNodeId]
выбирает любой BrowseNode
элемент в документе, что имеет дочерний узел BrowseNodeId
, string(BrowseNodeId)
выполняется в контексте узла, он возвращает все BrowseNodeId
потомков и преобразует первое в строку (пустую строку, если ни один узел не найден).
Используя идентификатор в качестве ключа массива, дубликаты будут удалены.
Это немного уродливо, но сводит его в структуру, с которой я могу работать, не совсем то, что я хотел, но, возможно, достаточно близко, чтобы использовать.
$json = json_encode($xml);
$array = json_decode($json,TRUE);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
foreach($it as $v) {
$values[] = $v;
}
$DOM = new DOMDocument();
$DOM->loadHTML($xml);
$XPATH = new DOMXpath($DOM);
// Gets all BrowseNodeId anywhere within the document
$r = $XPATH->query("//BrowseNodeId");
// Gets only BrowseNodeIds that re directly below a BrowseNodes and then a BrowseNodes
$r = $XPATH->query("/BrowseNodes/BrowseNode/BrowseNodeId");
Возможно, вы захотите использовать первый запрос Xpath, чтобы получить все элементы Ids.
$r = $XPATH->query("//BrowseNodeId");
foreach ($r as $element) { // $element will be a DOMElement object
$original = $element;
while($element->nextSibling != null) {
if("Name" == $element->tagName) {
echo "The ID for " . $element->nodeValue . " is " . $original->nodeValue;
}
$element = $element->nextSibling;
}
}
Это дает вам старт / идею по крайней мере.
Это не проверено.
Рассматривать XSLT чтобы сгладить исходный XML, а затем перебрать результат, чтобы заполнить ваш массив:
// Load the XML source and XSLT string
$doc = simplexml_load_file('Input.xml');
$xslstr = '<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="/BrowseNodes">
<xsl:copy>
<xsl:apply-templates select="descendant::BrowseNodeId"/>
</xsl:copy>
</xsl:template>
<xsl:template match="BrowseNodeId">
<data>
<xsl:copy-of select="."/>
<xsl:copy-of select="following-sibling::Name"/>
</data>
</xsl:template>
</xsl:transform>';
$xsl = new SimpleXMLElement($xslstr);
// Configure and run the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
$newXML = $proc->transformToXML($doc);
// Populate flattened array
$output = new SimpleXMLElement($newXML);
values = [];
foreach ($output->data as $line){
$inner = [];
$inner[] = (string)$line->BrowseNodeId;
$inner[] = (string)$line->Name;
$values[] = $inner;
}
Новый XML
<?xml version="1.0" encoding="UTF-8"?>
<BrowseNodes>
<data>
<BrowseNodeId>1342630031</BrowseNodeId>
<Name>Chargers</Name>
</data>
<data>
<BrowseNodeId>389516011</BrowseNodeId>
<Name>Accessories</Name>
</data>
<data>
<BrowseNodeId>389514011</BrowseNodeId>
<Name>Sat Nav, GPS, Navigation & Accessories</Name>
</data>
<data>
<BrowseNodeId>560800</BrowseNodeId>
<Name>Categories</Name>
</data>
<data>
<BrowseNodeId>560798</BrowseNodeId>
<Name>Electronics & Photo</Name>
</data>
<data>
<BrowseNodeId>340328031</BrowseNodeId>
<Name>Car Chargers</Name>
</data>
<data>
<BrowseNodeId>340327031</BrowseNodeId>
<Name>Chargers</Name>
</data>
<data>
<BrowseNodeId>560826</BrowseNodeId>
<Name>Accessories</Name>
</data>
<data>
<BrowseNodeId>1340509031</BrowseNodeId>
<Name>Mobile Phones & Communication</Name>
</data>
<data>
<BrowseNodeId>560800</BrowseNodeId>
<Name>Categories</Name>
</data>
<data>
<BrowseNodeId>560798</BrowseNodeId>
<Name>Electronics & Photo</Name>
</data>
</BrowseNodes>
Массив значений
array(11) {
[0]=>
array(2) {
[0]=>
string(10) "1342630031"[1]=>
string(8) "Chargers"}
[1]=>
array(2) {
[0]=>
string(9) "389516011"[1]=>
string(11) "Accessories"}
[2]=>
array(2) {
[0]=>
string(9) "389514011"[1]=>
string(38) "Sat Nav, GPS, Navigation & Accessories"}
[3]=>
array(2) {
[0]=>
string(6) "560800"[1]=>
string(10) "Categories"}
[4]=>
array(2) {
[0]=>
string(6) "560798"[1]=>
string(19) "Electronics & Photo"}
[5]=>
array(2) {
[0]=>
string(9) "340328031"[1]=>
string(12) "Car Chargers"}
[6]=>
array(2) {
[0]=>
string(9) "340327031"[1]=>
string(8) "Chargers"}
[7]=>
array(2) {
[0]=>
string(6) "560826"[1]=>
string(11) "Accessories"}
[8]=>
array(2) {
[0]=>
string(10) "1340509031"[1]=>
string(29) "Mobile Phones & Communication"}
[9]=>
array(2) {
[0]=>
string(6) "560800"[1]=>
string(10) "Categories"}
[10]=>
array(2) {
[0]=>
string(6) "560798"[1]=>
string(19) "Electronics & Photo"}
}