[PHP][DOM] Как наложить одно XML дерево на другое?

xintrea

Новичок
PHP:
[DOM] Как наложить одно XML дерево на другое?[/b]

Здравствуйте!

Раздумываю щас над такой задачкой. Есть два XML дерева - базовое и дополнительное, которое нужно "наложить" на базовое. Пример:

Базовое дерево: 
[code] 
    <query name="first_query"> 
        <!-- Новости --> 
        <table name="news"> 
            <field name="time"> 
                <about val="Время"/> 
                <size val="10"/> 
            </field> 
            <field name="title"> 
                <about val="Заголовок"/> 
                <size val="250"/> 
            </field> 
            <field name="text"> 
                <about val="Текст"/> 
                <size val="4096"/> 
            </field> 
        </table> 
        <!-- Картинки --> 
        <table name="picture"> 
            <field name="time"> 
                <about val="Время добавления файла"/> 
                <size val="10"/> 
            </field> 
            <field name="file"> 
                <about val="Файл картинки"/> 
                <filename_size val="1000"/> 
            </field> 
            <field name="title"> 
                <about val="Описание файла"/> 
                <size val="250"/> 
            </field> 
        </table> 
    </query> 
[/code]

Дополнительное дерево: 
[code]
    <query name="second_query"> 
        <!-- Новости --> 
        <table name="news"> 
            <field name="time"> 
                <defaultvalue val="autotime"/> 
                <size val="20"/> 
            </field> 
            <field name="public"> 
                <about val="Разрешить публикацию новости"/> 
                <size val="1"/> 
            </field> 
        </table> 
        <!-- Картинки --> 
        <table name="picture"> 
            <field name="file"> 
                <pic_resize val="320x200"/> 
            </field> 
        </table> 
    </query> 
[/code]

Дополнительное дерево должно накладываться на базовое по следующим правилам: 

1. Должны добавляться узлы, которых нет в исходном дереве. 

2. Значения атрибутов, переопределенных в дополнительном дереве, должны заменить собой значения атрибутов в базовом дереве.

То есть, результирующее дерево должно выглядеть так:
[code]
     <query name="reult_query"> 
        <!-- Новости --> 
        <table name="news"> 
            <field name="time"> 
                <about val="Время"/> 
                <size val="20"/> 
                <defaultvalue val="autotime"/> 
            </field> 
            <field name="title"> 
                <about val="Заголовок"/> 
                <size val="250"/> 
            </field> 
            <field name="text"> 
                <about val="Текст"/> 
                <size val="4096"/> 
            </field> 
            <field name="public"> 
                <about val="Разрешить публикацию новости"/> 
                <size val="1"/> 
            </field> 
        </table> 
        <!-- Картинки --> 
        <table name="picture"> 
            <field name="time"> 
                <about val="Время добавления файла"/> 
                <size val="10"/> 
            </field> 
            <field name="file"> 
                <about val="Файл картинки"/> 
                <filename_size val="1000"/> 
                <pic_resize val="320x200"/> 
            </field> 
            <field name="title"> 
                <about val="Описание файла"/> 
                <size val="250"/> 
            </field> 
        </table> 
    </query> 
[/code]

Вопрос: Каким образом это сделать?

Я уже попробовал преобразовывать DOM-деревья в ассоциативные массивы вот такго формата: [url]http://paste.org.ru/?d2qfug[/url]. 

Затем объединяю массивы с помощью функции [b]array_merge_recursive_distinct()[/b], которую можно найти тут: [url]http://php.net/manual/en/function.array-merge-recursive.php[/url], а затем полученный массив обратно преобразовывать в DOM.

Но проблема в том, что, например, элементы table и элементы field обозначены числовыми индексами. И узел

<pic_resize val="320x200"/>

вставляется в нужный элемент <table> (так как в обоих деревьях элементов <table> два), но в <field name="time"> вместо <field name="file">. Заодно, у этого <field> появляются два атрибута name.

Это происходит потому, что в базовом дереве во второй таблице первым идет элемент <field name="time">, а в дополнительном дереве первым идет элемент <field name="file">. Этот первый элемент дополнительного дерева и накладывается на первый элемент базового дерева. А должен накладываться на второй. Но я не пойму, как это сделать?

Я тут уже думаю сделать какое-нибудь другое, линейное представление деревьев, чтобы решить эту задачу. Но что-то не могу придумать формат в котором легко можно будет сращивать деревья.

Кто что думает по этому вопросу? Может уже есть готовые накладывалки XML деревьев друг на друга? Я не нашел, но может я ищу не в той области?
 

xintrea

Новичок
Автор оригинала: slach
это можно сделать с помощью XSLT шаблона
погуглите на предмет XSLT Identity Transformation

-~{}~ 23.07.10 18:21:

http://php.net/manual/en/book.xsl.php
Ну, я уже впринципе сделал что хотел, только пришлось изменить формат XML так, чтобы все неконечные элементы (ветви) обязательно имели атрибут name, чтобы их можно было однозначно идентифицировать. И преобразование в массив делаю не с числовыми индексами (которые фактически представляют собой номера ChildNode), а с текстовыми, соответсвующими name каждой ветки.

Тогда сращивание массивов происходит однозначно.

Но я посмотрел про тождественные трансформации через XSLT, но не понял, как через них сращивать два XML дерева?
 
Сверху