Have written a Python code to transform a XML file to a particular format using XSL stylesheet. Python code below:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from lxml import etree
def transform(xmlPath, xslPath):
# read xsl file
xslRoot = etree.fromstring(open(xslPath).read())
transform = etree.XSLT(xslRoot)
# read xml
xmlRoot = etree.fromstring(open(xmlPath).read())
# transform xml with xslt
transRoot = transform(xmlRoot)
# return transformation result
return etree.tostring(transRoot)
if __name__ == '__main__':
print(transform('talendtest.xml', 'style2.xsl'))
style2.xsl content:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user="http://mycompany.com/mynamespace" version="1.0">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:for-each select="/rowData/rows">
<xsl:value-of select="Plan"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="Purpose"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="Description"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="Travel_Date"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="Length_of_trip_days"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="Air_Travel"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="Total_Travel"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="Total_Airfare"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="Total_Hotel"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="Total_Meals"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="Total_Rental_Car"/>
<xsl:text>|</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
XML file content:
<?xml version="1.0" encoding="UTF-8"?>
<call method="SOME" callerName="Travel_call">
<credentials login="abc.com" password="XXXXX" instanceCode="YYYY"></credentials>
<importDataOptions planOrActuals="Plan" allowParallel="false" moveBPtr="false" useMappings="true"></importDataOptions>
<version name="API Test Version" isDefault="false"></version>
<sheet name="Travel" isUserAssigned="false"></sheet>
<rowData>
<header>Plan|Purpose|Air Travel|Description|Travel Date|Length of Trip (Days)|Travel Costs >|Total Travel|Total Airfare|Total Hotel|Total Meals|Total Rental Car</header>
<rows>
<Plan>Sales - North</Plan>
<Purpose>Seminar/Conference</Purpose>
<Description>Conf</Description>
<Travel_Date>1/11/2015</Travel_Date>
<Length_of_trip_days>3</Length_of_trip_days>
<Air_travel>Yes - International</Air_travel>
<Total_Travel>2455.0</Total_Travel>
<Total_Airfare>1300.0</Total_Airfare>
<Total_Hotel>750.0</Total_Hotel>
<Total_Meals>255.0</Total_Meals>
<Total_Rental_Car>150.0</Total_Rental_Car>
</rows>
</rowData>
</call>
Desired file content:
<call method="SOME" callerName="Travel_call">
<credentials login="abc.com" password="XXXXX" instanceCode="YYYY"></credentials>
<importDataOptions planOrActuals="Plan" allowParallel="false" moveBPtr="false" useMappings="true"></importDataOptions>
<version name="API Test Version" isDefault="false"></version>
<sheet name="Travel" isUserAssigned="false"></sheet>
<rowData>
<header>Plan|Purpose|Air Travel|Description|Travel Date|Length of Trip (Days)|Travel Costs|Total Travel|Total Airfare|Total Hotel|Total Meals|Total Rental Car</header>
<rows>
<row> Sales - North|Seminar/Conference|Conf|1/11/2015|3|Yes - International|2455.0|1300.0|750.0|255.0|150.0</row>
</rows>
</rowData>
</call>
However when I run the program python xslapply.py the output I receive is None. There are no other details displayed. Please can someone help with if there is an issue with the XML file or the XSL styling applied which is not returning any actual result.
Your XSLT returns an empty string, because:
does not select anything (because
rowData
is not the root element, and not the child of the current node). Try changing it to:There are other problems. Why is your output method set to
text
, when your expected output is XML? And you're not doing anything to output the other elements besidesrowData
.Added:
To add a
row
for every record set (i.erows
), try it this way:Note: if every
rows
has exactly the elements listed in the header, and in the same order, you could make the last template simply: