I'm really struggling transforming some XML. I'm usually OK with XSLT but it might be the root element causing me problems in the XML. I would really appreciate some guidance.
Existing XML:
<?xml version="1.0" ?>
<asx:abap xmlns:asx="http://www.testsrvXXXX.com/abdxml" version="1.0">
<asx:values>
<META>
<XOUTPUT>
<FIELDNAME>Make</FIELDNAME>
<OUTPUTLEN>000130</OUTPUTLEN>
<TYPE>CHAR</TYPE>
<SRC_TEXT>Make</SRC_TEXT>
</XOUTPUT>
<XOUTPUT>
<FIELDNAME>Model</FIELDNAME>
<OUTPUTLEN>000130</OUTPUTLEN>
<TYPE>CHAR</TYPE>
<SRC_TEXT>Car Model</SRC_TEXT>
<XOUTPUT>
<XOUTPUT>
<FIELDNAME>Engine</FIELDNAME>
<OUTPUTLEN>000130</OUTPUTLEN>
<TYPE>CHAR</TYPE>
<SRC_TEXT>Engine Size</SRC_TEXT>
</XOUTPUT>
<XOUTPUT>
<FIELDNAME>Type</FIELDNAME>
<OUTPUTLEN>000130</OUTPUTLEN>
<TYPE>CHAR</TYPE>
<SRC_TEXT>Fuel Type</SRC_TEXT>
</XOUTPUT>
<XOUTPUT>
<FIELDNAME>Colour</FIELDNAME>
<OUTPUTLEN>000130</OUTPUTLEN>
<TYPE>CHAR</TYPE>
<SRC_TEXT>Paint Colour</SRC_TEXT>
</XOUTPUT>
<XOUTPUT>
<FIELDNAME>Doors</FIELDNAME>
<OUTPUTLEN>000130</OUTPUTLEN>
<TYPE>NUM</TYPE>
<SRC_TEXT>Door Count</SRC_TEXT>
</XOUTPUT>
<XOUTPUT>
<FIELDNAME>Speed</FIELDNAME>
<OUTPUTLEN>000130</OUTPUTLEN>
<TYPE>NUM</TYPE>
<SRC_TEXT>Top Speed</SRC_TEXT>
</XOUTPUT>
<XOUTPUT>
<FIELDNAME>Service</FIELDNAME>
<OUTPUTLEN>000130</OUTPUTLEN>
<TYPE>CHAR</TYPE>
<SRC_TEXT>Service Intervals</SRC_TEXT>
</XOUTPUT>
</META>
<Y_OUTPUT>
<item>
<Make>Volkswagen</Make>
<Service>20000 KM</Service>
<Model>Golf</Model>
<Speed>190 KPH</Speed>
<Engine>1400 CC</Engine>
<Type>Diesel</Type>
<Colour>Black</Colour>
<Doors>3</Doors>
</item>
<item>
<Make>Ford</Make>
<Service>15000 KM</Service>
<Model>Fiesta</Model>
<Speed>180 KPH</Speed>
<Engine>1400 CC</Engine>
<Type>Petrol</Type>
<Colour>Red</Colour>
<Doors>5</Doors>
</item>
</Y_OUTPUT>
</asx:values>
</asx:abap>
The transformed XML needs to look like:
<Cars>
<Record>
<Make>Volkswagen</Make>
<Service>20000 KM</Service>
<Model>Golf</Model>
<Speed>190 KPH</Speed>
<Engine>1400 CC</Engine>
<Type>Diesel</Type>
<Colour>Black</Colour>
<Doors>3</Doors>
</Record>
<Record>
<Make>Ford</Make>
<Service>15000 KM</Service>
<Model>Fiesta</Model>
<Speed>180 KPH</Speed>
<Engine>1400 CC</Engine>
<Type>Petrol</Type>
<Colour>Red</Colour>
<Doors>5</Doors>
</Record>
</Cars>
My XSLT:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each select="Y_OUTPUT/ITEM">
<Cars>
<Record>
<Make><xsl:value-of select="Make"/></Make>
<Service><xsl:value-of select="Service"/></Service>
<Model><xsl:value-of select="Model"/></Model>
<Speed><xsl:value-of select="Speed"/></Speed>
<Engine><xsl:value-of select="Engine"/></Engine>
<Type><xsl:value-of select="Type"/></Type>
<Colour><xsl:value-of select="Colour"/></Colour>
<Doors><xsl:value-of select="Doors"/></Doors>
</Record>
</Cars>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
I think the problem is that you match /
in your template, but then start the xsl:for-each
select with Y_OUTPUT
and Y_OUTPUT
isn't the root element in your XML input.
You can update your xsl:for-each
to start where the template match left off (the current context).
You can also add a second xsl:for-each
to handle the creation of the child elements without namespace declarations...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<Cars>
<xsl:for-each select="*/Y_OUTPUT/item">
<Record>
<xsl:for-each select="*">
<xsl:element name="{local-name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</Record>
</xsl:for-each>
</Cars>
</xsl:template>
</xsl:stylesheet>
An alternative would be to use xsl:apply-templates
.
It's a few more lines, but a good pattern (push) to use when creating more complicated transforms...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<Cars>
<xsl:apply-templates select="*/Y_OUTPUT/item"/>
</Cars>
</xsl:template>
<xsl:template match="item">
<Record>
<xsl:apply-templates/>
</Record>
</xsl:template>
<xsl:template match="item/*">
<xsl:element name="{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
It helps to fully understand XSLTs built-in template rules to know how the template above is working.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.