PHP XML DOM синтаксический анализ смешанного контента

У меня есть XML-документ, который хорошо определен с xsd-файлом. Xml-документ содержит содержимое, подобное приведенному ниже:

<foo>
   <bar>text <element a="1" b="2" c="3" /> and some more text</bar>
   <bar>Just text</bar>
</foo>

Я хотел использовать PHP, чтобы разобрать его, чтобы просто вернуть одно из значений атрибута (которое будет решено в другом месте в коде), встроенное с остальной частью текста, для этого примера я хотел бы «B», и выходные данные должны быть:

"text 2 and some more text"
"Just text"

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

Я бы предпочел использовать метод DOMDocument PHP для этого. Хотя я не изучал XPath, я был бы готов изучить его, если это сделает эту задачу возможной. Я бы также рассмотрел изменение формата вложенного узла, хотя это было бы последним средством.

Я использую DOMdocument для поиска узла:

$xml= new DOMDocument();
$xml->load(XMLPATH); 
$node = $xml->getElementsByTagName("element")->item(0);

Затем все следующие игнорируют вложенный элемент:

$node->nodeValue;
$node->C14N(); 

Я также следовал этому руководству безрезультатно:
Как получить innerHTML DOMNode?

Спасибо за помощь.

2 ответа

  1. Вы можете использовать XPath, чтобы выбрать text()узлы и @bвыбрать атрибут, и оператор union |приведет все в правильном порядке:

    $xml = <<<EOD
    <foo>
       <bar>text <element a="1" b="2" c="3" /> and some more text</bar>
       <bar>Just text</bar>
    </foo>
    EOD;
    
    $doc = new DOMDocument();
    $doc->loadXML($xml);
    
    $xpath = new DOMXPath($doc);
    $nodeList = $xpath->query('//foo//text() | //foo//element/@b', $doc);
    
    $result = '';
    
    for ($i = 0; $i < $nodeList->length; $i++) {
        $result .= $nodeList[$i]->textContent;
    }
    echo $result;
    

    Результат

       text 2 and some more text
       Just text
    
  2. Следующий код должен дать вам представление о том, как достичь цели без использования XPath:

    <?php
    $xml = '<foo>
        <bar>text <element a="1" b="2" c="3" /> and some more text</bar>
        <bar>Just text</bar>
    </foo>'; // Your example XML.
    
    $attr = 'b'; // Attribute of <element> you are interested in.
    
    $doc = new DOMDocument();
    $doc->loadXml($xml);
    
    foreach($doc->documentElement->getElementsByTagName('bar') as $bar)
    {
        $text = '';
        foreach($bar->childNodes as $child)
        {
            switch($child->nodeType)
            {
            case XML_ELEMENT_NODE:
                if($child->nodeName == 'element')
                    $text .= $child->getAttribute($attr);
                break;
            case XML_TEXT_NODE:
                $text .= $child->textContent;
                break;
            }
        }
        echo $text . PHP_EOL;
    }