Выровнять структуру XML в PHP и добавить все значения в массив

У меня есть несколько узлов просмотра, возвращенных из 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 &amp; Accessories</Name>
<Ancestors>
<BrowseNode>
<BrowseNodeId>560800</BrowseNodeId>
<Name>Categories</Name>
<IsCategoryRoot>1</IsCategoryRoot>
<Ancestors>
<BrowseNode>
<BrowseNodeId>560798</BrowseNodeId>
<Name>Electronics &amp; 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 &amp; Communication</Name>
<Ancestors>
<BrowseNode>
<BrowseNodeId>560800</BrowseNodeId>
<Name>Categories</Name>
<IsCategoryRoot>1</IsCategoryRoot>
<Ancestors>
<BrowseNode>
<BrowseNodeId>560798</BrowseNodeId>
<Name>Electronics &amp; Photo</Name>
</BrowseNode>
</Ancestors>
</BrowseNode>
</Ancestors>
</BrowseNode>
</Ancestors>
</BrowseNode>
</Ancestors>
</BrowseNode>
</Ancestors>
</BrowseNode>
</BrowseNodes>

0

Решение

Использование 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 потомков и преобразует первое в строку (пустую строку, если ни один узел не найден).

Используя идентификатор в качестве ключа массива, дубликаты будут удалены.

1

Другие решения

Это немного уродливо, но сводит его в структуру, с которой я могу работать, не совсем то, что я хотел, но, возможно, достаточно близко, чтобы использовать.

$json = json_encode($xml);

$array = json_decode($json,TRUE);

$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));

foreach($it as $v) {

$values[] = $v;

}
0

$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;
}
}

Это дает вам старт / идею по крайней мере.

Это не проверено.

0

Рассматривать 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 &amp; Accessories</Name>
</data>
<data>
<BrowseNodeId>560800</BrowseNodeId>
<Name>Categories</Name>
</data>
<data>
<BrowseNodeId>560798</BrowseNodeId>
<Name>Electronics &amp; 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 &amp; Communication</Name>
</data>
<data>
<BrowseNodeId>560800</BrowseNodeId>
<Name>Categories</Name>
</data>
<data>
<BrowseNodeId>560798</BrowseNodeId>
<Name>Electronics &amp; 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"}
}
0
По вопросам рекламы [email protected]