2016-02-04 2 views
1

Есть несколько сообщений, относящихся к PHP и SimpleXML с пространствами имен, но ни один из них не рассматривает проблему, которую я испытываю. Вот небольшой кусок XML-представителя большего тела, с которым у меня возникают проблемы, тем не менее, проблема та же. Я не могу получить любые запросы xpath для возврата данных, которые я хочу. Соблюдайте следующиеУстранение неполадок XML с пространствами имен с использованием PHP SimpleXML Xpath

$xml = <<<EOD 
<blah:book xmlns:chap="http://example.org/chapter-title" xmlns:blah="urn:blah"> 
    <blah:wrap> 
     <chap:wrap> 
      <title>My Book</title> 
      <chapter id="1"> 
       <title>Chapter 1</title> 
       <para>Donec velit. Nullam eget tellus vitae</para> 
      </chapter> 
      <chapter id="2"> 
       <title>Chapter 2</title> 
       <para>Lorem ipsum dolor sit amet</para> 
      </chapter> 
     </chap:wrap> 
    </blah:wrap> 
</blah:book> 
EOD; 

пространствам имен из «бэ» и «ЧАП», поскольку они находятся в первом теле, кажется, не создающих проблемы. Если я запускаю следующий код PHP с XPath запроса следующие результаты:

$sxe = new SimpleXMLElement($xml); 
$result = $sxe->xpath('/node()/*/*'); 
var_dump($result); 

// gives me 
array(1) { 
    [0]=> 
    object(SimpleXMLElement)#2 (2) { 
    ["title"]=> 
    string(7) "My Book" 
    ["chapter"]=> 
    array(2) { 
     [0]=> 
     object(SimpleXMLElement)#4 (3) { 
     ["@attributes"]=> 
     array(1) { 
      ["id"]=> 
      string(1) "1" 
     } 
     ["title"]=> 
     string(9) "Chapter 1" 
     ["para"]=> 
     string(37) "Donec velit. Nullam eget tellus vitae" 
     } 
     [1]=> 
     object(SimpleXMLElement)#5 (3) { 
     ["@attributes"]=> 
     array(1) { 
      ["id"]=> 
      string(1) "2" 
     } 
     ["title"]=> 
     string(9) "Chapter 2" 
     ["para"]=> 
     string(26) "Lorem ipsum dolor sit amet" 
     } 
    } 
    } 
} 

Проблема происходит, когда «глава» является более распространенным, как этот:

$xml = <<<EOD 
<blah:book xmlns:chap="http://example.org/chapter-title" xmlns:blah="urn:blah"> 
    <blah:wrap> 
     <chap:wrap> 
      <chap:title>My Book</chap:title> 
      <chap:chapter id="1"> 
       <chap:title>Chapter 1</chap:title> 
       <chap:para>Donec velit. Nullam eget tellus vitae</chap:para> 
      </chap:chapter> 
      <chap:chapter id="2"> 
       <chap:title>Chapter 2</chap:title> 
       <chap:para>Lorem ipsum dolor sit amet</chap:para> 
      </chap:chapter> 
     </chap:wrap> 
    </blah:wrap> 
</blah:book> 
EOD; 

После чего тот же код PHP выше результаты в этой структуре:

array(1) { 
    [0]=> 
    object(SimpleXMLElement)#2 (0) { 
    } 
} 

Я пытался регистрации имен:

$sxe = new SimpleXMLElement($xml); 
$sxe->registerXPathNamespace('chap', 'http://example.org/chapter-title'); 
$result = $sxe->xpath('/node()/*/*'); 
var_dump($result); 

Но все тот же результат:

array(1) { 
    [0]=> 
    object(SimpleXMLElement)#2 (0) { 
    } 
} 

Я пробовал количество различных запросов XPath ни один из которых не будет возвращать все тело XML в структуре массива, как показано выше, от первого тела XML , Вот пара, но я пробовал дикие вещи из отчаяния, ни одна из которых не сработала.

$result = $sxe->xpath('/node()/chap:*/*'); 
$result = $sxe->xpath('/node()/*/chap:*'); 

Некоторые должности предложили удаление всех пространств имен, а затем не беспокоиться об этом, но, там должен быть способ, чтобы разобрать его восстановить весь организм так же, как это возможно в первом примере. К сожалению, я прихожу с пустыми руками. Я также признаю, что я не понимаю, почему одно вхождение пространства имен «chap» в первом теле не вызывает проблемы для исходного запроса xpath. Я надеюсь, кто-то может указать мне в правильном направлении.

ответ

0

Может быть возможным решением является использование его в качестве выражения XPath:

$ результата = $ sxe-> XPath ('// л: книга/л: обертка');

xpath возвращает массив, из которого вы можете взять первый элемент. Это будет тип SimpleXMLElement, который вы можете использовать метод children и передать пространство имён.

Вы можете петлить детей в foreach, а переменная $res будет иметь тип SimpleXMLElement. Затем вы можете проверить, установлены ли свойства и получить ваши данные.

Например:

$xml = <<<EOD 
<blah:book xmlns:chap="http://example.org/chapter-title" xmlns:blah="urn:blah"> 
    <blah:wrap> 
     <chap:wrap> 
      <chap:title>My Book</chap:title> 
      <chap:chapter id="1"> 
       <chap:title>Chapter 1</chap:title> 
       <chap:para>Donec velit. Nullam eget tellus vitae</chap:para> 
      </chap:chapter> 
      <chap:chapter id="2"> 
       <chap:title>Chapter 2</chap:title> 
       <chap:para>Lorem ipsum dolor sit amet</chap:para> 
      </chap:chapter> 
     </chap:wrap> 
    </blah:wrap> 
</blah:book> 
EOD; 

$sxe = new SimpleXMLElement($xml); 

$result = $sxe->xpath('//blah:book/blah:wrap'); 
foreach ($result[0]->children('http://example.org/chapter-title') as $res) { 
    if (isset($res->title)) { 
     $bookTitle = $res->title->__toString(); 
    } 
    if (isset($res->chapter)) { 
     foreach ($res->chapter as $chapter) { 
      $chapterTitle = $chapter->title->__toString(); 
      $chapterPara = $chapter->para->__toString(); 
     } 
    } 
} 

Demo

+0

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

Смежные вопросы