Я ищу эффективный способ реорганизации частей XML-документа, который содержит несколько дочерних элементов такого типа, как «SmallCat» или «BigCat».Условная реорганизация XML
Вот правила:
- Все для узлов Хабитат, кроме должны быть переданы через; атрибуты и все.
- Узлы среды обитания с менее чем двумя экземплярами либо BigCat, либо SmallCat должны быть пройдены.
Входной документ выглядит следующим образом:
<Zoo>
<Habitat HabitatID="habitat.cage.1">
<Type>Cats</Type>
<Food>Birds</Food>
<BigCat AnimalID="Tiger.1">
<Type>Bengal</Type>
</BigCat>
<SmallCat AnimalID="bobcat.1">
<Type>Bobcat</Type>
</SmallCat>
<BodyTemp>endothermic</BodyTemp>
</Habitat>
<Habitat HabitatID="cage.2">
<Type>Cats</Type>
<Food>Birds</Food>
<SmallCat AnimalID="tabycat.1">
<Type>Tabycat</Type>
</SmallCat>
<BodyTemp>endothermic</BodyTemp>
</Habitat>
<ConsessionStand>
<Type>PopcornStand</Type>
</ConsessionStand>
</Zoo>
Вывод должен выглядеть следующим образом:
<Zoo>
<Habitat HabitatID="sub_habitat.1.habitat.cage.1">
<Type>Cats</Type>
<Food>Birds</Food>
<BigCat AnimalID="Tiger.1">
<Type>Bengal</Type>
</BigCat>
</Habitat>
<Habitat HabitatID="sub_habitat.2.habitat.cage.1">
<Type>Cats</Type>
<Food>Birds</Food>
<SmallCat AnimalID="bobcat.1">
<Type>Bobcat</Type>
</SmallCat>
</Habitat>
<Habitat HabitatID="habitat.cage.1">
<BodyTemp>endothermic</BodyTemp>
<Child>
<HabitatID>sub_habitat.1.habitat.cage.1</HabitatID>
</Child>
<Child>
<HabitatID>sub_habitat.2.habitat.cage.1</HabitatID>
</Child>
</Habitat>
<Habitat HabitatID="cage.2">
<Type>Cats</Type>
<Food>Birds</Food>
<SmallCat AnimalID="tabycat.1">
<Type>Tabycat</Type>
</SmallCat>
<BodyTemp>endothermic</BodyTemp>
</Habitat>
<ConsessionStand>
<Type>PopcornStand</Type>
</ConsessionStand>
</Zoo>
Идеальное решение будет использовать XSLT, но любое решение (баш, JavaScript, PHP, Python , ruby, go и т. д.), который выполняет свою работу, является достойным соперником.
Вот реализация, которая составляет ~ 90% работы.
Это решение не реконструировать первый Хабитат узел со ссылками на новые sub_habitat дочерних узлов.
<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()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Habitat[count(BigCat|SmallCat) > 1]">
<xsl:param name="i"/>
<xsl:for-each select="BigCat|SmallCat">
<xsl:choose>
<xsl:when test="self::BigCat">
<Habitat HabitatID="sub_habitat.{position()}.{../@HabitatID}">
<xsl:copy-of select="../*[not(self::SmallCat|self::BodyTemp)]"/>
</Habitat>
</xsl:when>
<xsl:when test="self::SmallCat">
<Habitat HabitatID="sub_habitat.{position()}.{../@HabitatID}">
<xsl:copy-of select="../*[not(self::BigCat|self::BodyTemp)]"/>
</Habitat>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Итоговый результат представлен здесь.
<Zoo>
<Habitat HabitatID="sub_habitat.1.habitat.cage.1">
<Type>Cats</Type>
<Food>Birds</Food>
<BigCat AnimalID="Tiger.1">
<Type>Bengal</Type>
</BigCat>
</Habitat>
<Habitat HabitatID="sub_habitat.2.habitat.cage.1">
<Type>Cats</Type>
<Food>Birds</Food>
<SmallCat AnimalID="bobcat.1">
<Type>Bobcat</Type>
</SmallCat>
</Habitat>
<Habitat HabitatID="cage.2">
<Type>Cats</Type>
<Food>Birds</Food>
<SmallCat AnimalID="tabycat.1">
<Type>Tabycat</Type>
</SmallCat>
<BodyTemp>endothermic</BodyTemp>
</Habitat>
<ConsessionStand>
<Type>PopcornStand</Type>
</ConsessionStand>
</Zoo>
У вас есть актуальный вопрос? –
@ Michael.hor257k: Во-первых, можно ли решить эту проблему с помощью XSLT? Я недостаточно эксперт, чтобы позитивный пример. Во-вторых, если да, может ли кто-нибудь предоставить рабочий пример. В-третьих, если проблема не может быть решена с помощью XSLT, какое оптимальное решение будет выглядеть на каком-то другом языке? – Amvoxite
"* можно ли решить эту проблему с помощью XSLT? *« Я считаю, что это возможно, но это не служба написания кода. –