Не получается преобразовать xml через xslt
Есть xml:
<recordCollection>
<record>
<Object>
<Item>
<Name>Наименование1</Name>
</Item>
</Object>
<IPv4>
<Item>
<IPадресV4>IPv4-адрес1111</IPадресV4>
<ID>3444</ID>
</Item>
<Item>
<IPадресV4>IPv4-адрес2222</IPадресV4>
<ID>3445</ID>
</Item>
</IPv4>
<IPv6>
<Item>
<IPадрес>IPv6-адрес111</IPадрес>
<ID>3444</ID>
</Item>
<Item>
<IPадрес>IPv6-адрес222</IPадрес>
<ID>3445</ID>
</Item>
</IPv6>
</record>
</recordCollection>
Нужно преобразовать его вот в такой:
<alert>
<object>Наименование1</object>
<rows>
<row>
<IPv4>IPv4-адрес1111</IPv4>
<IPv6> IPv6-адрес1111</IPv6>
</row>
<row>
<IPv4>IPv4-адрес2222</IPv4>
<IPv6> IPv6-адрес222</IPv6>
</row>
</rows>
</alert>
Как это сделать с помощью xslt?
с помощью нейронки смог сделать такой xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Главная инструкция -->
<xsl:template match="/recordCollection">
<alert>
<!-- Наименование объекта -->
<object>
<xsl:value-of select="record/Object/Item/Name"/>
</object>
<!-- Таблица с объединенными данными -->
<rows>
<!-- Цикл по всем Item'ам в блоке IPv4 -->
<xsl:for-each select="record/IPv4/Item">
<xsl:variable name="currentId" select="ID"/>
<!-- Строка таблицы -->
<row>
<!-- IPv4 -->
<IPv4>
<xsl:value-of select="IPадресV4"/>
</IPv4>
<!-- Найти соответствующее значение IPv6 по ID -->
<xsl:variable name="ipv6Node" select="../../IPv6/Item[ID = $currentId]"/>
<!-- Если нашли, то вывести IPv6 -->
<xsl:if test="$ipv6Node">
<IPv6>
<xsl:value-of select="$ipv6Node/IPадрес"/>
</IPv6>
</xsl:if>
</row>
</xsl:for-each>
</rows>
</alert>
</xsl:template>
</xsl:stylesheet>
Минус в том, что этот вариант фиксируется на количестве item-ов ipv4,но в моём случае ipv4 может быть 1, а ipv6 два три и т.д. .
Ответы (1 шт):
в моём случае ipv4 может быть 1, а ipv6 два три и т.д.
Как это должно выглядеть если у вас 1 ipv4 и 3 ipv6? Или наоборот, 3 ipv4 и 1 ipv6?
Mинимальный, самодостаточный и воспроизводимый пример для всех возможных сценариев отсутствует. Так что я стреляю с бедра.
Попробуйте следующее решение.
Мы используем "Itemlist" индекс, указанный элементом <xsl:key>
для всего XML-документа. Таким образом не имеет значения сколько XML элементов IPv4 или IPv6.
Переменная $currentId
содержит уникальные значения ID идентификаторов в цикле.
Исходный XML
<recordCollection>
<record>
<Object>
<Item>
<Name>Наименование1</Name>
</Item>
</Object>
<IPv4>
<Item>
<IPадресV4>IPv4-адрес1111</IPадресV4>
<ID>3444</ID>
</Item>
<Item>
<IPадресV4>IPv4-адрес2222</IPадресV4>
<ID>3445</ID>
</Item>
</IPv4>
<IPv6>
<Item>
<IPадрес>IPv6-адрес111</IPадрес>
<ID>3444</ID>
</Item>
<Item>
<IPадрес>IPv6-адрес222</IPадрес>
<ID>3445</ID>
</Item>
<Item>
<IPадрес>IPv6-адрес222a</IPадрес>
<ID>3445</ID>
</Item>
<Item>
<IPадрес>IPv6-адрес333</IPадрес>
<ID>3770</ID>
</Item>
</IPv6>
</record>
</recordCollection>
XSLT 1.0
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="utf-8"
omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="Itemlist" match="Item" use="ID"/>
<xsl:template match="/recordCollection">
<alert>
<!-- Наименование объекта -->
<object>
<xsl:value-of select="record/Object/Item/Name"/>
</object>
<!-- Таблица с объединенными данными -->
<rows>
<xsl:for-each select="//Item[count(. | key('Itemlist',ID)[1]) = 1][ID]">
<xsl:variable name="currentId"
select="ID"/>
<row>
<xsl:for-each select="//Item[ID=$currentId]">
<xsl:if test="IPадресV4">
<IPv4>
<xsl:value-of select="IPадресV4"/>
</IPv4>
</xsl:if>
<xsl:if test="IPадрес">
<IPv6>
<xsl:value-of select="IPадрес"/>
</IPv6>
</xsl:if>
</xsl:for-each>
</row>
</xsl:for-each>
</rows>
</alert>
</xsl:template>
</xsl:stylesheet>
Выходной XML
<alert>
<object>Наименование1</object>
<rows>
<row>
<IPv4>IPv4-адрес1111</IPv4>
<IPv6>IPv6-адрес111</IPv6>
</row>
<row>
<IPv4>IPv4-адрес2222</IPv4>
<IPv6>IPv6-адрес222</IPv6>
<IPv6>IPv6-адрес222a</IPv6>
</row>
<row>
<IPv6>IPv6-адрес333</IPv6>
</row>
</rows>
</alert>