I want to convert a name/value xml to element xml using xsl. I tried every method which I could find. I refered this post, Convert Name/Value Pair XML to Elements using XSLT and made the changes, but my resultant xml doesn't show the key values.
Below are my code files:
xml file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<METSM xmlns="metsmng" xmlns:ns2="http://www.w3.org/1999/xlink">
<Case id="MTMzo29276" ns2:href="https://metsm.com/api/case/MTMzo29276">
<Column name="BU">SU</Column>
<Column name="Summary">Hardware failure</Column>
<Column name="Project">Servers</Column>
<Column name="Priority">High</Column>
<Column name="Status">Working</Column>
<Column name="Open-Date">01/23/2017 23:11:16</Column>
</Case>
<Case id="MTMzo29739" ns2:href="https://metsm.com/api/case/MTMzo29739">
<Column name="BU">AICM</Column>
<Column name="Summary">Create a new profile</Column>
<Column name="Project">Datacentre</Column>
<Column name="Priority">Low</Column>
<Column name="Status">Open</Column>
<Column name="Open-Date">10/04/2010 00:00:00</Column>
</Case>
</METSM>
xsl:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/METSM">
<METSM>
<xsl:for-each select="Case">
<Case>
<xsl:element name="{@id}">
<xsl:value-of select="."/>
</xsl:element>
<xsl:for-each select="Column">
<xsl:element name="{@name}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</Case>
</xsl:for-each>
</METSM>
</xsl:template>
</xsl:stylesheet>
Output required:
<METSM>
<Case>
<id> MTMzo29276 </id>
<BU> SU </BU>
<Summary> Hardware failure </Summary>
....
</Case>
<Case>
....
</Case>
</METSM>
What I am getting:
<?xml version="1.0" encoding="UTF-8"?>
SU
Hardware failed
Servers
High
Working
01/23/2017 23:11:16
AICM
Create a new profile
Datacentre
Low
Open
10/04/2010 00:00:00
I am not able to figure out the issue. How do I get the key names in my result xml file. Any help will be highly grateful. Thanks in advance.
EDIT: using below python code to generate the output xml file:
from lxml import etree
data = open(r'C:\Users\abc\Desktop\input-xsl.xsl')
xslt_content = data.read()
xslt_root = etree.XML(xslt_content)
dom = etree.parse(r'C:\Users\abc\Desktop\input-xml.xml')
transform = etree.XSLT(xslt_root)
result = transform(dom)
print(result)
It's because your XML is in the default namespace metsmng
. Since you're using XSLT 2.0, you can use xpath-default-namespace
...
XSLT 2.0
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xpath-default-namespace="metsmng">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/METSM">
<METSM>
<xsl:for-each select="Case">
<Case>
<id><xsl:value-of select="@id"/></id>
<xsl:for-each select="Column">
<xsl:element name="{@name}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</Case>
</xsl:for-each>
</METSM>
</xsl:template>
</xsl:stylesheet>
Also notice that I fixed your id
element output.
Output
<METSM>
<Case>
<id>MTMzo29276</id>
<BU>SU</BU>
<Summary>Hardware failure</Summary>
<Project>Servers</Project>
<Priority>High</Priority>
<Status>Working</Status>
<Open-Date>01/23/2017 23:11:16</Open-Date>
</Case>
<Case>
<id>MTMzo29739</id>
<BU>AICM</BU>
<Summary>Create a new profile</Summary>
<Project>Datacentre</Project>
<Priority>Low</Priority>
<Status>Open</Status>
<Open-Date>10/04/2010 00:00:00</Open-Date>
</Case>
</METSM>
You mentioned in the comments you are using lxml. If so, XSLT 2.0 is not supported; you'll need to use XSLT 1.0. What you'll need to do is bind the namespace to a prefix and use that prefix in your XPath's...
XSLT 1.0
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:m="metsmng" exclude-result-prefixes="m">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/m:METSM">
<METSM>
<xsl:for-each select="m:Case">
<Case>
<id><xsl:value-of select="@id"/></id>
<xsl:for-each select="m:Column">
<xsl:element name="{@name}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</Case>
</xsl:for-each>
</METSM>
</xsl:template>
</xsl:stylesheet>