Разбор XML-документа (odt-файл): как пошагово пройти по элементам для заполнения массива

Я пытаюсь разобрать XML-документ (content.xml odt-файла).

$reader = new XMLReader();
if (!$reader->open("content.xml")) die("Failed to open 'content.xml'");
// step through text:h and text:p elements to put them into an array
while ($reader->read()){
if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'text:h' || $reader->name === 'text:p')) {
echo $reader->expand()->textContent; // Put the text into array in correct order...
}
}
$reader->close();

Прежде всего мне нужно лишь немного подсказать, как правильно пройтись по элементам XML-файла. В моей попытке я могу пройтись по тексту: h-elements, но как мне получить другие элементы (text: p), не путая все …

Тем не менее я покажу вам мою конечную цель на всех. Пожалуйста, не думайте, что я прошу полное решение. Я просто записал все, чтобы показать, какая структура мне нужна. Я хочу решить эту проблему шаг за шагом

Содержимое этого xml-файла выглядит примерно так:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
[...]
<office:body>
<office:text text:use-soft-page-breaks="true">
<text:h text:style-name="P1" text:outline-level="2">Chapter 1</text:h>
<text:p text:style-name="Standard">Lorem ipsum. </text:p>

<text:h text:style-name="Heading3" text:outline-level="3">Subtitle 1</text:h>
<text:p text:style-name="Standard"><text:span text:style-name="T2">Something 1:</text:span> Lorem.</text:p>
<text:p text:style-name="Standard"><text:span text:style-name="T3">Something 2:</text:span><text:s/>Lorem ipsum.</text:p>
<text:p text:style-name="Standard"><text:span text:style-name="T4">Something 3:</text:span> Lorem ipsum.</text:p>

<text:h text:style-name="Heading3" text:outline-level="3">Subtitle 2</text:h>
<text:p text:style-name="Standard"><text:span text:style-name="T5">10</text:span><text:span text:style-name="T6">:</text:span><text:s/>Text (100%)</text:p>
<text:p text:style-name="Explanation">Further informations.</text:p>
<text:p text:style-name="Standard">9.7:<text:s/>Text (97%)</text:p>
<text:p text:style-name="Explanation">Further informations.</text:p>
<text:p text:style-name="Standard"><text:span text:style-name="T9">9.1:</text:span><text:s/>Text (91%)</text:p>
<text:p text:style-name="Explanation">Further informations.</text:p>
<text:p text:style-name="Explanation">More furter informations.</text:p>

[Subtitle 3 and 4]

<text:h text:style-name="Heading3" text:outline-level="3">Subtitle 5</text:h>
<text:p text:style-name="Standard"><text:span text:style-name="T5">10</text:span><text:span text:style-name="T6">:</text:span><text:s/>Text (100%)</text:p>
<text:p text:style-name="Explanation">Further informations.</text:p>
<text:p text:style-name="Standard">9.7:<text:s/>Text (97%)</text:p>
<text:p text:style-name="Explanation">Further informations.</text:p>
<text:p text:style-name="Standard"><text:span text:style-name="T9">9.1:</text:span><text:s/>Text (91%)</text:p>
<text:p text:style-name="Explanation">Further informations.</text:p>
<text:p text:style-name="Explanation">More furter informations.</text:p>

<text:h text:style-name="Heading3" text:outline-level="3">References</text:h>
<text:list text:style-name="LFO44" text:continue-numbering="true">
<text:list-item><text:p text:style-name="P25">blabla et al., Any Title p. 580-586</text:p></text:list-item>
<text:list-item><text:p text:style-name="P25">blabla et al., Any Title p. 580-586</text:p></text:list-item>
<text:list-item><text:p text:style-name="P25">blabla et al., Any Title p. 580-586</text:p></text:list-item>
<text:list-item><text:p text:style-name="P25">blabla et al., Any Title p. 580-586</text:p></text:list-item>
</text:list>

[Multiple Chapter like this]

</office:text>
</office:body>

Вы видите, что у «подглав» всегда есть стандартные элементы и необязательный элемент объяснения (также возможно несколько элементов объяснения для одного стандарта). Эта структура всегда одинакова …

Моя конечная цель — разделить всю информацию, чтобы получить Array-Output, например:

array() {
[1]=>
array() {
["chapter"]=>
string() "Chapter 1"["content"]=>
array() {
[0]=>
array() {
["subchapter"]=>
string() "Description"["content"]=>
array() {
[0]=>
array() {
["standard"]=>
string() "Lorem ipsum."["explanation"]=>
string(0) ""}
}
}
[1]=>
array() {
["subchapter"]=>
string() "Subtitle 1"["content"]=>
array() {
[0]=>
array() {
["standard"]=>
string() "Something 1: Lorem."["explanation"]=>
string() ""}
[1]=>
array() {
["standard"]=>
string() "Something 2: Lorem ipsum."["explanation"]=>
string() ""}
[2]=>
array() {
["standard"]=>
string() "Something 2: Lorem ipsum."["explanation"]=>
string() ""}
}
}
[2]=>
array() {
["subchapter"]=>
string() "Subtitle 2"["content"]=>
array() {
[0]=>
array() {
["standard"]=>
string() "10: Text (100%)"["explanation"]=>
string() "Further informations."}
[and so on]

0

Решение

редактировать:

Я вижу вашу проблему сейчас, спасибо за редактирование вопроса:

в вашем цикле

while ($reader->read()){

}

У вас есть несколько функций для получения узлов и значений:

$reader->value

даст значение (например, «Субтитры 1»)

$reader->getAttribute('text:style-name')

Должен получить часть ‘Heading3’

В целом, вы, вероятно, хотите что-то вроде этого в цикле while [псевдокод]:

 // set an index
$i = 0;
// get the parts fromt he xml we need
$name = $reader->name;
$attrib = $reader->getAttribute('text:style-name');
$value = $reader->value;

// if the attribute is a 'P1', then increment our index, as we need a new indentation in our array
if($value == 'P1'){
$i++;
}

$array[$i][$attrib]=$reader->value;

обратите внимание, что это сделает отступ только до одного уровня — похоже, вам нужно 4 уровня, так что вы, вероятно, должны иметь 4 индекса [$ i, $ k, $ k, $ l] и проверять каждый на предмет того, что требует отступа — P1, Heading3 и т. Д.

вы могли бы в конечном итоге

$array[$i][$j][$k] = $reader->value;

или т.п. Не забывайте переустанавливать все ваши субиндексы, когда вы увеличиваете индекс (например, если вы $ i ++, установите $ j = 0, $ k = 0 и т. Д.)

предыдущие ответы ниже:

SimpleXML может (вероятно) сделать это в несколько строк [если структура XML-файла уже вложена в правильный путь, который после быстрого просмотра выглядит так]: http://php.net/manual/en/book.simplexml.php

$xml = simplexml_load_file('content.xml');
$json = json_encode($xml);
$array = json_decode($json,TRUE);

print_r($array);

редактировать: вы также можете использовать xpath с simplexml, и вы можете делать такие вещи, как

echo $xml->{office:body}->{office:text}->{text.h}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]