能否用XSL 1.0将含不确定数量Field属性的XML归一化为键值对?
Yes, you can absolutely normalize this structure using XSLT 1.0!
Here's a straightforward solution that maps the header fields (from the first Record) to their corresponding values in subsequent records, producing clean key-value elements:
XSLT 1.0 Stylesheet
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="Table"> <NormalizedData> <!-- Store the first record (field names) in a variable --> <xsl:variable name="header-fields" select="Record[1]"/> <!-- Process all data records (skip the first header record) --> <xsl:for-each select="Record[position() > 1]"> <NormalizedRecord RecordNo="{@RecordNo}"> <!-- Iterate over every Field attribute in the current data record --> <xsl:for-each select="@*[starts-with(name(), 'Field')]"> <!-- Extract the numeric suffix from the Field attribute name --> <xsl:variable name="field-number" select="substring-after(name(), 'Field')"/> <!-- Look up the matching field name from the header record --> <xsl:variable name="field-name" select="$header-fields/@*[name() = concat('Field', $field-number)]"/> <!-- Create an element using the header field name and set its value --> <xsl:element name="{$field-name}"> <xsl:value-of select="."/> </xsl:element> </xsl:for-each> </NormalizedRecord> </xsl:for-each> </NormalizedData> </xsl:template> </xsl:stylesheet>
How It Works
- Header Capture: We first grab the first
Recordelement, which contains the field names (likeID,Author) mapped toField1,Field2, etc. - Data Processing: For each subsequent
Record, we loop through all attributes starting withField. - Field Mapping: For each
FieldNattribute, we extract the numberN, look up the corresponding field name from the header, then create a new element with that name and the attribute's value. - Preserve RecordNo: The original
RecordNoattribute is retained as an attribute on the outputNormalizedRecordelement.
Example Input & Output
Input 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" /> </Table>
Output XML
<NormalizedData> <NormalizedRecord RecordNo="2"> <ID>Book001</ID> <Author>Gambardella, Matthew</Author> <Title>XML Developer's Guide</Title> <Genre>Computer</Genre> <Price>44.95</Price> <Published>2000-10-01</Published> </NormalizedRecord> <NormalizedRecord RecordNo="3"> <ID>Book002</ID> <Author>Ralls, Kim</Author> <Title>Midnight Rain</Title> <Genre>Fantasy</Genre> <Price>5.95</Price> <Published>2000-12-16</Published> </NormalizedRecord> </NormalizedData>
Notes
- This assumes your
Fieldattributes are sequentially numbered (Field1, Field2, ...) and that the header record has matching numbers for all data fields. - If your field names contain characters invalid for XML element names (like spaces or special characters), you may need to adjust the code to sanitize the names (e.g., replacing spaces with underscores).
内容的提问来源于stack exchange,提问作者Brian Bates
相关产品推荐
相关产品推荐

