2017-01-05 4 views
0

Я хочу извлечь некоторые данные из xml.Как получить текстовый узел из xml

У меня есть этот XML:

<root> 
    <p>Some text</p> 
    <p>Even more text</p> 
    <span class="bla bla"> 
     <span class="currency">EUR</span> 19.95 
    </span> 
</root> 

и затем я запускаю этот PHP код

$xml = simplexml_load_string($xmlString); 
$json = json_encode($xml); 
$obj = json_decode($json); 
print_r($obj); 

и результат:

stdClass Object 
(
    [p] => Array 
     (
      [0] => Some text 
      [1] => Even more text 
     ) 

    [span] => stdClass Object 
     (
      [@attributes] => stdClass Object 
       (
        [class] => bla bla 
       ) 

      [span] => EUR 
     ) 
) 

Как получить недостающую строку " 19,95" ?

ответ

0

Не конвертируйте XML в JSON/массив. Это означает, что вы теряете информацию и функции.

SimpleXML is litmit, он работает с основным XML, но у него есть проблемы с предметами, такими как смешанные узлы. DOM позволяет упростить обработку в этом случае.

$xml = <<<'XML' 
<root> 
    <p>Some text</p> 
    <p>Even more text</p> 
    <span class="bla bla"> 
     <span class="currency">EUR</span> 19.95 
    </span> 
</root> 
XML; 

$document = new DOMDocument(); 
$document->loadXml($xml); 
$xpath = new DOMXpath($document); 

foreach($xpath->evaluate('/root/span[@class="bla bla"]') as $span) { 
    var_dump(
    $xpath->evaluate('string(span[@class="currency"][1])', $span), 
    $xpath->evaluate(
     'number(span[@class="currency"][1]/following-sibling::text()[1])', 
     $span 
    ) 
); 
} 

Xpath - язык выражения для извлечения частей DOM (Think SQL for XML). PHP имеет несколько способов доступа к нему. SimpleXMLElement::xpath() позволяет извлекать узлы в виде массивов объектов SimpleXMLElement. DOMXpath::query() позволяет получать списки узлов. Только DOMXpath::evaluate() позволяет извлекать списки узлов и скалярные значения.

В примере /root/span[@class="bla bla"] извлекаются все узлы узлов span, которые имеют данный атрибут класса. Для каждого из узлов он извлекает span с валютой класса в виде строки. Третье выражение выбирает первый следующий текстовый узел для сиблинга диапазона currency как число.

+0

Хотя это включает в себя некоторые аккуратные трюки с XPath, это массовое переполнение для описанной задачи. SimpleXML вообще не имеет проблем с этим XML, за исключением неполного вывода 'print_r'. – IMSoP

0

Не доверяйте выводам отладки, не конвертируйте их в JSON или массив и не переусердствуйте с проблемой.

Выведение этой строки так просто, как навигация к элементу и вторя его:

echo $xml->span; 

Или, чтобы получить его в переменный, явно приводятся к строке:

$foo = (string)$xml->span 

Или, если вы хотите чтобы использовать XPath, как в ответе ThW, вы можете найти диапазон, используя //span[@class="bla bla"] и эхо (обратите внимание, что ->xpath() возвращает массив, поэтому вы хотите, чтобы элемент 0 этого массива):

echo $xml->xpath('//span[@class="bla bla"]')[0]; 
Смежные вопросы