XML format change using XSL file in a Python code

2024/10/14 23:10:45

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 filexslRoot = etree.fromstring(open(xslPath).read())transform = etree.XSLT(xslRoot)# read xmlxmlRoot = etree.fromstring(open(xmlPath).read())# transform xml with xslttransRoot = transform(xmlRoot)# return transformation resultreturn 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 &gt;|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.

Answer

Your XSLT returns an empty string, because:

<xsl:for-each select="/rowData/rows">

does not select anything (because rowData is not the root element, and not the child of the current node). Try changing it to:

<xsl:for-each select="call/rowData/rows">

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 besides rowData.


Added:

To add a row for every record set (i.e rows), try it this way:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/><!-- identity transform -->
<xsl:template match="@*|node()"><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template><xsl:template match="rowData"><xsl:copy><xsl:copy-of select="header"/><rows><xsl:apply-templates select="rows"/></rows></xsl:copy>
</xsl:template> <xsl:template match="rows"><row><xsl:value-of select="concat(Plan, '|', Purpose, '|', Description, '|', Travel_Date, '|', Length_of_trip_days, '|', Air_Travel, '|', Total_Travel, '|', Total_Airfare, '|', Total_Hotel, '|', Total_Meals, '|', Total_Rental_Car)" /></row>
</xsl:template> </xsl:stylesheet>

Note: if every rows has exactly the elements listed in the header, and in the same order, you could make the last template simply:

<xsl:template match="rows"><row><xsl:for-each select="*"><xsl:value-of select="."/></xsl:for-each><xsl:if test="position()!=last()"><xsl:text>|</xsl:text></xsl:if></row>
</xsl:template> 
https://en.xdnf.cn/q/117900.html

Related Q&A

How to extract a specific value from a dictionary in python

I want to extract distance from google distance matrix API in Python. The objet it returned is a python dictionary.{destination_addresses: [Mumbai, Maharashtra, India ],origin_addresses: [Powai, Mumbai…

label on top of image in python

I am trying to display text on top of an image. Right now the text is below the image or if I put a row=0 in the grid disappears. I am assuming it is behind the image. I cant seem to get it to work. My…

plot multiple graphs from multiple files gnuplot

I have a set of files named like this:qd-dPZ-z1-1nn.dat qd-dPZ-z2-1nn.dat qd-dPZ-z4-1nn.dat qd-dPZ-z8-1nn.dat qd-dPZ-z16-1nn.dat qd-dPZ-z32-1nn.dat qd-dPZ-z1-2nn.dat qd-dPZ-z2-2nn.dat qd-dPZ-z4…

Python writing to CSV... TypeError: coercing to Unicode: need string or buffer, file found

outputList is a list of lists. [ [a,b,c], [d,e,f], [g,h,i] ] and I want to output it to a csv file with each list as a separate row. Im getting this error TypeError: coercing to Unicode: need string or…

Preserve Signature in Decorator python 2

I am writing a decorator which will catch TypeError for incorrect number of arguments in a function call and will print a customised message. The code is here:import inspectdef inspect_signature(f):def…

Gimp: start script without image

Well, Im trying to write a python plug-in for Gimp, but it wont start without first loading an image... What can I do about that?

Pywinauto: how the `findbestmatch` module works?

Im trying to understand how the findbestmatch module works. Here is an example.from pywinauto.application import Application from pywinauto.findbestmatch import find_best_match ditto=Application().conn…

How to get the surface from a rect/line

I am trying to find the point where a line collides with a brick in the arkanoid that i am making. The most logical way i found is getting the mask from the line and use collidemask as it returns the p…

Python readin .txt and put in an array with numpy

i want to create an array with numpy. The base is a .txt file which is given in the following form:i tried it with loadtxt:data = np.loadtxt("myfile.txt",delimiter=\n,skiprows = 1)The first r…

Running a PyQt4 script without a display

I would like to run a Python script that normally opens a Qt window remotely over a connection with no X11 forwarding. Is there any way to create some kind of virtual display that the window drawing ca…