Преобразование элементов XML в атрибуты XML с использованием XSLT
У нас есть текущая система, которая выводит XML файл, который находится в следующем формате:
<INVENTORY>
<ITEM>
<SERIALNUMBER>something</SERIALNUMBER>
<LOCATION>something</LOCATION>
<BARCODE>something</BARCODE>
</ITEM>
</INVENTORY>
Мне нужно использовать эти данные для загрузки в стандартную сетку .NET 2.0. Но для сетки XML должен быть в следующем формате:
<INVENTORY>
<ITEM serialNumber="something" location="something" barcode="something">
</ITEM>
</INVENTORY>
то есть. дочерние узлы элемента необходимо преобразовать в атрибуты элемента node.
Кто-нибудь знает, как это можно сделать с помощью XSLT?
Ответы
Ответ 1
Это должно работать:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="INVENTORY">
<INVENTORY>
<xsl:apply-templates/>
</INVENTORY>
</xsl:template>
<xsl:template match="ITEM">
<ITEM>
<xsl:for-each select="*">
<xsl:attribute name="{name()}">
<xsl:value-of select="text()"/>
</xsl:attribute>
</xsl:for-each>
</ITEM>
</xsl:template>
</xsl:stylesheet>
НТН
Ответ 2
Эти два шаблона должны делать это: -
<xsl:template match="ITEM">
<ITEM serialNumber="{SERIALNUMBER}" location="{LOCATION}" barcode="{BARCODE}" />
</xsl:template>
<xsl:template match="INVENTORY">
<INVENTORY>
<xsl:apply-templates />
</INVENTORY>
</xsl:template>
Ответ 3
Вот, пожалуй, самое простое решение, которое преобразует любые дочерние элементы ITEM
в его атрибуты и будет воспроизводить все остальное, как есть, при преобразовании имен элементов в имена любых желаемых атрибутов:
<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:variable name="vrtfNameMapping">
<item name="SERIALNUMBER" newName="serialNumber"/>
<item name="LOCATION" newName="location"/>
<item name="BARCODE" newName="barcode"/>
</xsl:variable>
<!-- -->
<xsl:variable name="vNameMapping" select=
"document('')/*/xsl:variable[@name='vrtfNameMapping']"/>
<!-- -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- -->
<xsl:template match="ITEM/*">
<xsl:attribute name=
"{$vNameMapping/*[@name=name(current())]/@newName}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
, когда указанное преобразование применяется к предоставленному XML-документу:
<INVENTORY>
<ITEM>
<SERIALNUMBER>something</SERIALNUMBER>
<LOCATION>something</LOCATION>
<BARCODE>something</BARCODE>
</ITEM>
</INVENTORY>
получен желаемый результат:
<INVENTORY>
<ITEM serialNumber="something" location="something" barcode="something"/>
</INVENTORY>
Обратите внимание на следующее:
-
Использование правило идентификации
-
Использование <xsl:strip-space elements="*"/>
-
Использование переменной vrtfNameMapping
без функции расширения xxx:node-set()
.
-
Тот факт, что мы обрабатываем любое сопоставление между именем и newName, а не только простой нижний корпус.
Ответ 4
Это должно сделать это:
<xsl:for-each select="//ITEM">
<xsl:element name="ITEM">
<xsl:attribute name="serialNumber">
<xsl:value-of select="SERIALNUMBER"/>
</xsl:attribute>
<xsl:attribute name="location">
<xsl:value-of select="LOCATION"/>
</xsl:attribute>
<xsl:attribute name="barcode">
<xsl:value-of select="BARCODE"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
Или используя ярлык David:
<xsl:for-each select="//ITEM">
<ITEM serialNumber="{SERIALNUMBER}" location="{LOCATION}" barcode="{BARCODE}"/>
</xsl:for-each>
Ответ 5
Если ваш источник выглядит так:
<row><a>1</a><b>2</b></row>
и вы хотите, чтобы он выглядел следующим образом:
<row a="1" b="2" />
то этот XSLT должен работать:
<xsl:template match="row">
<row a="{a}" b="{b}" />
</xsl:template>