Один из вариантов - использовать xsl:key
, который выбирает все атрибуты первого Record
и использует атрибуты name()
для ключа.
Атрибут Field1
необходимо будет обрабатывать иначе, чем другие, поскольку он используется в Parent
вместо Child
.
Пример ...
Ввод XML
<Table>
<Record RecordNo="1" Field1="ID" Field2="Author" Field3="Title" Field4="Genre" Field5="Price" Field6="Published" />
<Record RecordNo="2" Field1="Book001" Field2="Gambardella, Matthew" Field3="XML Developer's Guide" Field4="Computer" Field5="44.95" Field6="2000-10-01" />
<Record RecordNo="3" Field1="Book002" Field2="Ralls, Kim" Field3="Midnight Rain" Field4="Fantasy" Field5="5.95" Field6="2000-12-16" />
<Record RecordNo="4" Field1="Book003" Field2="Randall, Cynthia" Field3="Lover Birds" Field4="Romance" Field5="4.95" Field6="2000-09-02" />
</Table>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<!--Select all the attributes of the first Record and use the attributes
name for the key. See https://www.w3.org/TR/xslt-10/#key -->
<xsl:key name="keys" match="Record[@RecordNo=1]/@*" use="name()"/>
<xsl:template match="/Table">
<xsl:copy>
<!--Process Record elements, but do not process the Record
with the attribute RecordNo value of 1. That Record is only used for
the Key values.-->
<xsl:apply-templates select="Record[not(@RecordNo=1)]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Record">
<Parent>
<!--Process the attributes of Record, but do not process the RecordNo
attribute.-->
<xsl:apply-templates select="@*[not(name()='RecordNo')]">
<!--Sort by attribute name to guarantee the order they're processed.-->
<xsl:sort select="name()"/>
</xsl:apply-templates>
</Parent>
</xsl:template>
<xsl:template match="@Field1" priority="1">
<!--For the Field1 attribute, create an attribute. Since we know the name of
this attribute, we could also use key('keys','Field1') to get the name.
Also, the curly braces ({}) is an AVT (Attribute Value Template).
See https://www.w3.org/TR/xslt-10/#attribute-value-templates-->
<xsl:attribute name="{key('keys',name())}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="@*">
<!--For any other attributes, create a Child element. They key lookup is based on the
name of the attribute. (The second argument in key() corresponds to the "use"
attribute of xsl:key.)-->
<Child Key="{key('keys',name())}" Value="{.}"/>
</xsl:template>
</xsl:stylesheet>
выход
<Table>
<Parent ID="Book001">
<Child Key="Author" Value="Gambardella, Matthew"/>
<Child Key="Title" Value="XML Developer's Guide"/>
<Child Key="Genre" Value="Computer"/>
<Child Key="Price" Value="44.95"/>
<Child Key="Published" Value="2000-10-01"/>
</Parent>
<Parent ID="Book002">
<Child Key="Author" Value="Ralls, Kim"/>
<Child Key="Title" Value="Midnight Rain"/>
<Child Key="Genre" Value="Fantasy"/>
<Child Key="Price" Value="5.95"/>
<Child Key="Published" Value="2000-12-16"/>
</Parent>
<Parent ID="Book003">
<Child Key="Author" Value="Randall, Cynthia"/>
<Child Key="Title" Value="Lover Birds"/>
<Child Key="Genre" Value="Romance"/>
<Child Key="Price" Value="4.95"/>
<Child Key="Published" Value="2000-09-02"/>
</Parent>
</Table>
Fiddle: http://xsltfiddle.liberty -development.net / pPqsHTa / 2