Как получить все элементы в XML-файле, используя CURL и DOM, помещенные в массив? - PullRequest
1 голос
/ 18 апреля 2019

Мне нужна помощь с кодом.Я хочу получить все элементы в XML-файле, используя CURL и DOM, в массив.

Можете ли вы помочь мне с этим?

Мой PHP с кодом CURL показан ниже:

<?php

$key = 'ad12rqwagst3ewtgsdhdsdsfsdgsd';

$url = 'http://api.11street.my/rest/cateservice/category';

$request_body = 'xml data';

$headers = array(
    'openapikey: ' . $key,
    'Accept-Charset: utf-8',
    'Content-Type: application/xml'
);

$curl = curl_init($url);

curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($curl);
$arrXml = array();
$dom = new DOMDocument;
$dom->loadXML($result);

foreach ($dom->getElementsByTagName('dispEngNm') as $item) {
    $arrXml[] = $dom->saveXML($item) . "<br>" . "<hr>";
} 

print_r($arrXml);

?>

Пример кода XML-файла показан ниже, у меня есть три элемента:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
</ns2:categorys>
<ns2:category>
    <depth>1</depth>
    <dispEngNm>Women Clothing</dispEngNm>
    <dispNm>Women Clothing</dispNm>
    <dispNo>2021</dispNo>
    <parentDispNo>0</parentDispNo>
</ns2:category>
<ns2:category>
    <depth>2</depth>
    <dispEngNm>Women Tops</dispEngNm>
    <dispNm>Women Tops</dispNm>
    <dispNo>2051</dispNo>
    <parentDispNo>2021</parentDispNo>
</ns2:category>
<ns2:category>
    <depth>3</depth>
    <dispEngNm>Tanks &amp; Camisoles</dispEngNm>
    <dispNm>Tanks &amp; Camisoles</dispNm>
    <dispNo>2209</dispNo>
    <parentDispNo>2051</parentDispNo>
</ns2:category>
</ns2:categorys>

Вывод показан мне ниже:

Array ( [0] => Women Clothing
[1] => Women Tops
[2] => Tanks & Camisoles
[3] => T-shirts

Я просто могуполучить элемент "dispEngNm" в массив.Кто-нибудь знает, как можно получить другой элемент "dispNm", "dispNo", "parentDispNo" вместе с "dispEngNm" в массив?

Спасибо за вашу помощь!Желаю тебе хорошего дня!

Ответы [ 4 ]

0 голосов
/ 18 апреля 2019

Возможно общее преобразование в массив, но в большинстве случаев вы просто теряете функции и данные. DOM включает в себя Xpath, поэтому большую часть времени имеет смысл читать данные непосредственно в структуру SPECIFIC массив / объект. В вашем случае у вас есть список записей с отношениями родитель-ребенок.

Ваш XML содержит префикс пространства имен ns2, но его определение отсутствует. Найдите атрибут xmlns:ns2 - его значение является фактическим пространством имен.

$xml = <<<'XML'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:categorys xmlns:ns2="urn:ns2">
<ns2:category>
    <depth>1</depth>
    <dispEngNm>Women Clothing</dispEngNm>
    <dispNm>Women Clothing</dispNm>
    <dispNo>2021</dispNo>
    <parentDispNo>0</parentDispNo>
</ns2:category>
<ns2:category>
    <depth>2</depth>
    <dispEngNm>Women Tops</dispEngNm>
    <dispNm>Women Tops</dispNm>
    <dispNo>2051</dispNo>
    <parentDispNo>2021</parentDispNo>
</ns2:category>
<ns2:category>
    <depth>3</depth>
    <dispEngNm>Tanks &amp; Camisoles</dispEngNm>
    <dispNm>Tanks &amp; Camisoles</dispNm>
    <dispNo>2209</dispNo>
    <parentDispNo>2051</parentDispNo>
</ns2:category>
</ns2:categorys>
XML;

// this needs to be the value of the xmlns:ns2 attribute
$ns_categories = 'urn:ns2';

$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
// register an prefix for the namespace
$xpath->registerNamespace('c', $ns_categories);

$categories = [];
$tree = [];
// iterate the categories
foreach ($xpath->evaluate('//c:categorys/c:category') as $category) {
    // casting a node list in Xpath will return the content of the first node
    $id = (int)$xpath->evaluate('number(dispNo)', $category);
    $parentId = (int)$xpath->evaluate('number(parentDispNo)', $category);
    // store category data 
    $categories[$id] = [
        'id' => $id,
        'parent_id' => $parentId,
        'depth' => (int)$xpath->evaluate('number(depth)', $category),
        'caption' => $xpath->evaluate('string(dispNm)', $category),
        'caption_english' => $xpath->evaluate('string(dispEngNm)', $category),
    ];
    // store child ids for each parent 
    if (!isset($tree[$parentId])) {
      $tree[$parentId] = [];
    }
    $tree[$parentId][] = $id; 
}

var_dump($categories, $tree);   

Основные различия в том, что если вы читаете результат общего преобразования, ключи массива могут иметь разные имена или могут отсутствовать. Структура результата напрямую зависит от ввода. Если вы читаете данные в определенную структуру (как в моем примере), вы знаете, какие есть ключи массива.

0 голосов
/ 18 апреля 2019

Комбинируя имеющийся у вас код и используя возможность SimpleXML легко перебирать дочерние элементы, приведенный ниже код сначала ищет элементы <category> (getElementsByTagName() не беспокоится о пространствах имен), а затем импортирует его в SimpleXML, так что вы можете просто foreach() над дочерними элементами и добавить их в рабочий массив (используя имя тега в качестве ключа). Это просто копирует все дочерние данные в ассоциативный массив ...

$dom = new DOMDocument;
$dom->loadXML($result);

foreach ($dom->getElementsByTagName('category') as $item) {
    $sxml = simplexml_import_dom($item);
    $newData = [];
    foreach ( $sxml as $tag => $value ) {
        $newData[$tag] = (string)$value;
    }
    $arrXml[] = $newData;
}

print_r($arrXml);

дает ...

Array
(
    [0] => Array
        (
            [depth] => 1
            [dispEngNm] => Women Clothing
            [dispNm] => Women Clothing
            [dispNo] => 2021
            [parentDispNo] => 0
        )

    [1] => Array
        (
            [depth] => 2
            [dispEngNm] => Women Tops
            [dispNm] => Women Tops
            [dispNo] => 2051
            [parentDispNo] => 2021
        )

    [2] => Array
        (
            [depth] => 3
            [dispEngNm] => Tanks & Camisoles
            [dispNm] => Tanks & Camisoles
            [dispNo] => 2209
            [parentDispNo] => 2051
        )

)
0 голосов
/ 18 апреля 2019

может быть, вы ищете childNodes свойство?

$arrXml = array();
foreach($dom->getElementsByTagName("category") as $cat){
    $curr=array();
    foreach($cat->childNodes as $child){
            $curr[$child->nodeName]=$dom->saveXML($child);
    }
    $arrXml[]=$curr;
}
unset($cat,$curr,$child);
print_r($arrXml);

рабочий пример:

<?php

$xml=<<<'XML'
<ns2:category>
    <depth>1</depth>
    <dispEngNm>Women Clothing</dispEngNm>
    <dispNm>Women Clothing</dispNm>
    <dispNo>2021</dispNo>
    <parentDispNo>0</parentDispNo>
</ns2:category>
<ns2:category>
    <depth>2</depth>
    <dispEngNm>Women Tops</dispEngNm>
    <dispNm>Women Tops</dispNm>
    <dispNo>2051</dispNo>
    <parentDispNo>2021</parentDispNo>
</ns2:category>
<ns2:category>
    <depth>3</depth>
    <dispEngNm>Tanks &amp; Camisoles</dispEngNm>
    <dispNm>Tanks &amp; Camisoles</dispNm>
    <dispNo>2209</dispNo>
    <parentDispNo>2051</parentDispNo>
</ns2:category>
XML;
$dom = new DOMDocument;
@$dom->loadHTML($xml);
$arrXml = array();
foreach($dom->getElementsByTagName("category") as $cat){
    $curr=array();
    foreach($cat->childNodes as $child){
            $curr[$child->nodeName]=$dom->saveXML($child);
    }
    $arrXml[]=$curr;
}
unset($cat,$curr,$child);
print_r($arrXml);
  • Кстати, если вы на самом деле не хотите xml, а просто текстовое содержимое, измените

$curr[$child->nodeName]=$dom->saveXML($child);

с

$curr[$child->nodeName]=$child->textContent;

вместо этого, и он будет содержать текст дочернего элемента, а не xml

Кстати, вот что вышеприведенный пример кода с патчем textContent выдает:

Array
(
    [0] => Array
        (
            [depth] => 1
            [dispengnm] => Women Clothing
            [dispnm] => Women Clothing
            [dispno] => 2021
            [parentdispno] => 0
        )

    [1] => Array
        (
            [depth] => 2
            [dispengnm] => Women Tops
            [dispnm] => Women Tops
            [dispno] => 2051
            [parentdispno] => 2021
        )

    [2] => Array
        (
            [depth] => 3
            [dispengnm] => Tanks & Camisoles
            [dispnm] => Tanks & Camisoles
            [dispno] => 2209
            [parentdispno] => 2051
        )

)
0 голосов
/ 18 апреля 2019

Просто измените этот код:

foreach ($dom->getElementsByTagName('dispEngNm') as $item) {
    $arrXml[] = $dom->saveXML($item) . "<br>" . "<hr>";
}

на этот код:

$allTags = $dom->getElementsByTagName('ns2:category');
for ($i =0; $i < $allTags.length; $i++) {
    $childLen = $allTags[i].childNodes.length;
    $innerChilds = $allTags[i].firstChild;
    for ($j = 0; $j < $childLen; $j++) {
        $arrXml[] = $dom->saveXML($innerChilds.innerHTML) . "<br>" . "<hr>"; 
        $innerChilds = $innerChilds.nextSibling;
    }
}

В приведенном выше коде я просто загружаю все дочерние узлы ns2:category, которые могут работать.

Примечание: я не проверял код.Вы можете проверить это и внести изменения, если требуется.

...