помощь в чтении вложенного XML с использованием xmlreader в php - PullRequest
1 голос
/ 09 февраля 2009
<root>
  <thing>
    <specs>
      <spec1 />
      <spec3 />
      <spec2 />
    </specs>
    <details />
    <more_info>
      <info1 />
      <info2 />
    </more_info>
  </thing>
</root>


Итак, я получил этот пример XML и проблема в том, что я не могу получить значения innerxml,
, когда я использую $reader->readInnerXML(), он возвращает всю строку, хотя я уверен, что мой XML действителен
я хотел получить значения spec1, spec2, spec3 отдельно

код довольно длинный, поэтому я разместил его здесь
Я застрял с этим на 3 дня, T_T бедный меня, я бы с радостью принял любые исправления

Ответы [ 3 ]

4 голосов
/ 09 февраля 2009

Это зависит от того, что вы подразумеваете под «стоимостью». Если у вас есть что-то вроде

<spec3 />Value</spec3>

Тогда readInnerXML должен дать вам вашу ценность.

Если ваше значение в атрибуте,

<spec1 foo="my attribute" />

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

Наконец, если узел содержит больше вложенного XML,

<spec2><foo><baz thing="la de da">Value</baz></foo></spec2>

В этот момент нет прямого пути для читателя понять ценности / элементы внутри него. Вам нужно будет выполнить одно из следующих действий

  1. Измените код синтаксического анализа вашего читателя, чтобы подключаться к элементам на этих глубинах
  2. Возьмите кусок XML из readInnerXML и начните его анализ со вторым экземпляром XMLReader,
  3. Возьмите кусок XML из readInnerXML и начните его анализ с другой библиотекой синтаксического анализа XML.

Вот пример кода для разбора атрибутов

$reader = new XMLReader();
$reader->xml(trim('
<root>
  <thing>
    <specs>
      <spec1 foo="my attribute">Value</spec1>
      <spec3>
      My Text
      </spec3>
      <spec2 foo="foo again" bar="another attribute" baz="yet another attribute" />
    </specs>
    <details />
    <more_info>
      <info1 />
      <info2 />
    </more_info>
  </thing>
</root> 
'));

$last_node_at_depth = array();
$already_processed  = array();
while($reader->read()){
    $last_node_at_depth[$reader->depth] = $reader->localName;
    if(
    $reader->depth > 0 && 
    $reader->localName != '#text' &&   
    $last_node_at_depth[($reader->depth-1)] == 'specs' &&
    !in_array ($reader->localName,$already_processed)
    ){          
        echo "\n".'Processing ' . $reader->localName . "\n";
        $already_processed[] = $reader->localName;
        echo '--------------------------------------------------'."\n";
        echo 'The Value for the inner node ';           
        echo ' is [';
        echo trim($reader->readInnerXML());
        echo ']'."\n";

        if($reader->attributeCount > 0){
            echo 'This node has attributes, lets process them' . "\n";

            //grab attribute by name
            echo '    Value of attribute foo: ' . $reader->getAttribute('foo') . "\n";

            //or use the reader to itterate through all the attributes
            $length = $reader->attributeCount;
            for($i=0;$i<$length;$i++){
                //now the reader is pointing at attributes instead of nodes
                $reader->moveToAttributeNo($i);
                echo '    Value of attribute ' . $reader->localName;
                echo ': ';
                echo $reader->value;
                echo "\n";
            }
        }
        //echo $reader->localName . "\n";        
    }        
}
0 голосов
/ 09 февраля 2009

Не уверен, если это то, что вы спрашиваете, но simplexml может использоваться для чтения данных XML (значения каждого из элементов, а не атрибуты). Например, для вашей вещи / спецификации:

$xmlobj = simplexml_load_file($xmlfile);
$extracteddata = $xmlobj->thing->specs->spec1;

выдаст вам содержимое элемента spec1.

Пример: Если бы элемент был <spec1>1234</spec1>, приведенный выше код вернул бы "1234"

0 голосов
/ 09 февраля 2009

Это работает как рекламируется :

readInnerXML

Считывает содержимое текущего узла, включая дочерние узлы и разметку.

Я думаю, что ваша путаница может быть между узлами и атрибутами. <spec1 /> не является атрибутом - это узел без дочерних элементов. Написание <spec1 /> - это просто сокращение для <spec1></spec1>. Так что вам нужно либо использовать фактические атрибуты:

<root>
  <thing>
    <specs spec1="" spec3="" spec2="" />
    <details />
    <more_info info1="" info2="" />
  </thing>
</root>

или прочитайте эти узлы.

Во всяком случае. Я не уверен, что это только потому, что вы показываете нам пример кода или нет, но именование узлов spec1, spec2, spec3 и т. Д., Вероятно, не очень хорошая идея. Имена узлов не обязательно должны быть уникальными в XML.

...