Intereting Posts
Отправить форму (jquery) и показать результаты в colorbox Такой же скрипт cURL работает в dev. Не могу понять, почему не в производстве WordPress ACF: как добавить строки в поле ретранслятора, прикрепленные к пользователю с помощью настраиваемого кода (PHP) как использовать хэш-функцию для хранения ~ 4 миллионов изображений в файловой системе Изменение объектов в returnCallback () PHPUnit Mocks превышено максимальное время выполнения программы phpseclib 'getElement (s) By' в PHP-классе SimpleXML, как в PHP-DomDocument? Японские персонажи на Magento PDF Ошибка PHP с преобразованием объекта в массивы Загрузите видеофайлы с помощью PHP и сохраните их в соответствующей папке и введите запись в базу данных Вставка PHP с значениями массива, tablename CData в simplexml открыт из XMLReader Вопросы по загрузке файлов PHP Как считывать данные из памяти телефона с помощью Google laravel 5.1 говорит для всех других маршрутов, что кроме ('/'), что 404 страница не найдена на онлайн-сервере Amazon с использованием ec2

Объединение групп узлов XML

Im работает с PHP5, и мне нужно преобразовать XML в следующем виде:

<list> <item label="(1)">some text</item> <item label="(2)"> <anotherNode>some text</anotherNode <item label="a">some text</item> <item label="b">some text</item> </item> </list> 

В нечто подобное:

 <list> <item label="(1)">some text</item> <item label="(2)"> <anotherNode>some text</anotherNode> <list> <!-- opening new wrapper node--> <item label="a">some text</item> <item label="b">some text</item> </list> <!-- closing new wrapper node--> </item> </list> 

Как вы можете видеть выше, мне нужно добавить узел-оболочку к любым узлам «item», которые уже не завернуты узлом «list».

Каковы возможные решения для преобразования исходного xml в целевой xml?

ОБНОВЛЕНО:

Примечание 1: Любой узел или группа узлов <item> должен быть обернут узлом <list> если он уже не завернут.

Примечание 2: Заказ содержимого должен быть сохранен.

Примечание 3: Если есть узлы <item> до и после <anotherNode> . Он должен трансформировать это:

 <list> <item label="(1)">some text</item> <item label="(2)"> <item label="a">some text</item> <item label="b">some text</item> <anotherNode>some text</anotherNode> <item label="c">some text</item> <item label="d">some text</item> </item> </list> 

в это:

 <list> <item label="(1)">some text</item> <item label="(2)"> <list> <!-- opening new wrapper node--> <item label="a">some text</item> <item label="b">some text</item> </list> <!-- closing new wrapper node--> <anotherNode>some text</anotherNode> <list> <!-- opening new wrapper node--> <item label="c">some text</item> <item label="d">some text</item> </list> <!-- closing new wrapper node--> </item> </list> 

Благодаря,

Это преобразование :

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="node()|@*" name="identity"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="item/item[1]"> <list> <xsl:apply-templates mode="copy" select=".| following-sibling::item"/> </list> </xsl:template> <xsl:template match="item" mode="copy"> <xsl:call-template name="identity"/> </xsl:template> <xsl:template match="item/item[not(position()=1)]"/> </xsl:stylesheet> 

при применении к предоставленному XML-документу :

 <list> <item label="(1)">some text</item> <item label="(2)"> <anotherNode>some text</anotherNode> <item label="a">some text</item> <item label="b">some text</item> </item> </list> 

дает желаемый, правильный результат :

 <list> <item label="(1)">some text</item> <item label="(2)"> <anotherNode>some text</anotherNode> <list> <item label="a">some text</item> <item label="b">some text</item> </list> </item> </list> 

Обратите внимание :

  1. Использование и переопределение правила Identity .

  2. Подавление определенных элементов.

  3. Обработка некоторых элементов с использованием другого режима .

Обновление :

ОП добавил дополнительные требования:

« В случае наличия item элемента перед anothernode и после него каждая такая группа item элемента должна быть заключена в отдельный list »

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:key name="kfollnonitem" match="item" use="generate-id(preceding-sibling::*[not(self::item)][1])"/> <xsl:key name="kprecnonitem" match="item" use="generate-id(following-sibling::*[not(self::item)][1])"/> <xsl:template match="node()|@*" name="identity"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="*[not(self::list)]/item[1]"> <list> <xsl:apply-templates mode="copy" select="key('kprecnonitem', generate-id(following-sibling::*[not(self::item)][1]) )"/> </list> </xsl:template> <xsl:template match= "*[not(self::list) and item]/*[not(self::item)]"> <xsl:call-template name="identity"/> <list> <xsl:apply-templates mode="copy" select="key('kfollnonitem', generate-id())"/> </list> </xsl:template> <xsl:template match="item" mode="copy"> <xsl:call-template name="identity"/> </xsl:template> <xsl:template match="item/item[not(position()=1)]"/> </xsl:stylesheet> 

когда это преобразование выполняется против XML-документа :

 <list> <item label="(1)">some text</item> <item label="(2)"> <item label="a">some text</item> <item label="b">some text</item> <anotherNode>some text</anotherNode> <item label="c">some text</item> <item label="d">some text</item> </item> </list> 

получается желаемый, правильный результат :

 <list> <item label="(1)">some text</item> <item label="(2)"> <list> <item label="a">some text</item> <item label="b">some text</item> </list> <anotherNode>some text</anotherNode> <list> <item label="c">some text</item> <item label="d">some text</item> </list> </item> </list> 

Эта таблица стилей:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="@*|node()" name="identity"> <xsl:copy> <xsl:apply-templates select="@*|node()[1]" /> </xsl:copy> <xsl:apply-templates select="following-sibling::node()[1]" /> </xsl:template> <xsl:template match="*[not(self::list)] /item[not(preceding-sibling::*[1][self::item])]"> <list> <xsl:call-template name="identity"/> </list> <xsl:apply-templates select="following-sibling::node() [not(self::item)][1]" /> </xsl:template> <xsl:template match="*[not(self::list)] /item[not(following-sibling::*[1][self::item])]"> <xsl:copy> <xsl:apply-templates select="@*|node()[1]" /> </xsl:copy> </xsl:template> </xsl:stylesheet> 

Вывод:

 <list> <item label="(1)">some text</item> <item label="(2)"> <anotherNode>some text</anotherNode> <list> <item label="a">some text</item> <item label="b">some text</item> </list> </item> </list> 

Кроме того, эта таблица стилей:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:key name="kItemByFirstSibling" match="item[preceding-sibling::*[1][self::item]]" use="generate-id(preceding-sibling::item [not(preceding-sibling::*[1][self::item])][1])"/> <xsl:template match="@*|node()" name="identity"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <xsl:template match="*[not(self::list)]/item"/> <xsl:template match="*[not(self::list)] /item[not(preceding-sibling::*[1][self::item])]" priority="1"> <list> <xsl:for-each select=".|key('kItemByFirstSibling',generate-id())"> <xsl:call-template name="identity"/> </xsl:for-each> </list> </xsl:template> </xsl:stylesheet> 

Примечание . Первая таблица стилей использует большинство мелкозернистых трансверсалей (она будет обертывать любой узел после первого item ). Второе отображение полной рекурсивной идентичности стилей.

Изменить : адресация нового запроса, с новым входом, вывод обеих таблиц стилей:

 <list> <item label="(1)">some text</item> <item label="(2)"> <list> <item label="a">some text</item> <item label="b">some text</item> </list> <anotherNode>some text</anotherNode> <list> <item label="c">some text</item> <item label="d">some text</item> </list> </item> </list> 

Вы не обращались к этому в исходном вопросе, поэтому это может не потребоваться. Но если вход имеет несколько последовательностей элементов <item> которые необходимо обернуть, которые отделены друг от друга другими элементами-братьями, например:

 <list> <item label="(1)">some text</item> <item label="(2)"> <item label="a">some text</item> <item label="b">some text</item> <anotherNode>some text</anotherNode> <item label="c">some text</item> <item label="d">some text</item> </item> </list> 

более ранние ответы, я думаю, объединяют элементы <item> , изменяя их порядок:

 <list> <item label="(1)">some text</item> <item label="(2)"> <list> <!-- opening new wrapper node--> <item label="a">some text</item> <item label="b">some text</item> <item label="c">some text</item> <item label="d">some text</item> </list> <!-- closing new wrapper node--> <anotherNode>some text</anotherNode> </item> </list> 

Вам это нужно или вы хотите их обернуть отдельно?

 <list> <item label="(1)">some text</item> <item label="(2)"> <list> <!-- opening new wrapper node--> <item label="a">some text</item> <item label="b">some text</item> </list> <!-- closing new wrapper node--> <anotherNode>some text</anotherNode> <list> <!-- opening new wrapper node--> <item label="c">some text</item> <item label="d">some text</item> </list> <!-- closing new wrapper node--> </item> </list> 

Если последнее, вероятно, будет проще всего использовать конструкцию XSLT 2.0 <xsl:for-each-group group-adjacent="name()" /> . Я не знаю, доступен ли PHP 5 XSLT 2.0, но если вы можете использовать такую ​​вещь, см. Эту хорошую статью .