Transforming XML Attributes into XML Elements - xslt

I have the following XML input:
<?xml version="1.0" encoding="utf-8"?>
<DOCUMENT>
<EXTERNALFILES>
<PRIMARYFILE FileName="C:\MSSB\POC\Exports\13f78581-1501-4dd0-8cf3-a5a300ba4083\121110-26-2001031100092.TIF" />
</EXTERNALFILES>
<OCRTEXTFILES />
<DOCUMENTINDEX Name="A2iA_CheckAmount">3304.49</DOCUMENTINDEX>
<DOCUMENTINDEX Name="A2iA_CheckCAR">3304.49</DOCUMENTINDEX>
<DOCUMENTINDEX Name="A2iA_CheckCodeline_OnUs1">28557833</DOCUMENTINDEX>
<DOCUMENTINDEX Name="A2iA_CheckCodeline_Transit">031100092</DOCUMENTINDEX>
<DOCUMENTINDEX Name="A2iA_CheckDate">10-26-2001</DOCUMENTINDEX>
<DOCUMENTINDEX Name="A2iA_CheckLAR">3304.49</DOCUMENTINDEX>
<DOCUMENTINDEX Name="A2iA_CheckNumber">1211</DOCUMENTINDEX>
<DOCUMENTINDEX Name="A2iA_CheckPayeeName">BCBSD</DOCUMENTINDEX>
<DOCUMENTINDEX Name="CheckPayerName">SOFTPRO NORTH AMERICA, INC.</DOCUMENTINDEX>
</DOCUMENT>
I need to transform this into the following output:
<?xml version="1.0" encoding="utf-8"?>
<DOCUMENT>
<A2iA_CheckAmount>3304.49</A2iA_CheckAmount>
<A2iA_CheckCAR>3304.49</A2iA_CheckCAR>
<A2iA_CheckLAR>3304.49</A2iA_CheckLAR>
<A2iA_CheckAccountNumber>28557833</A2iA_CheckAccountNumber>
<A2iA_CheckRoutingNumber>031100092</A2iA_CheckRoutingNumber>
<A2iA_CheckNumber>1211</A2iA_CheckNumber>
<A2iA_CheckAmount>3304.49</A2iA_CheckAmount>
<A2iA_CheckPayeeName>BCBSD</A2iA_CheckPayeeName>
<CheckPayerName>SOFTPRO NORTH AMERICA, INC</CheckPayerName>
</DOCUMENT>
I am using the following XSLT code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:value-of select="concat('<DOCUMENT>')"/>
<xsl:template match="/*">
<xsl:for-each select="DOCUMENT/DOCUMENTINDEX/#*">
<xsl:value-of select="concat('<', name(), '>', ., '</', name(), '>')"/>
</xsl:for-each>
<xsl:value-of select="concat('</DOCUMENT>')"/>
</xsl:template>
I tested this with an online XSLT Tester and it threw a non-descriptive error. I am new to XSLT Transformation. Any help will be greatly appreciated. Thank You.

One possibility to achieve this is the following simple one(EDITED):
<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:template match="/DOCUMENT">
<xsl:element name="Document">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="DOCUMENTINDEX">
<xsl:element name="{#Name}">
<xsl:value-of select="text()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
It gives the output (EDITED)
<Document>
<A2iA_CheckAmount>3304.49</A2iA_CheckAmount>
<A2iA_CheckCAR>3304.49</A2iA_CheckCAR>
<A2iA_CheckCodeline_OnUs1>28557833</A2iA_CheckCodeline_OnUs1>
<A2iA_CheckCodeline_Transit>031100092</A2iA_CheckCodeline_Transit>
<A2iA_CheckDate>10-26-2001</A2iA_CheckDate>
<A2iA_CheckLAR>3304.49</A2iA_CheckLAR>
<A2iA_CheckNumber>1211</A2iA_CheckNumber>
<A2iA_CheckPayeeName>BCBSD</A2iA_CheckPayeeName>
<CheckPayerName>SOFTPRO NORTH AMERICA, INC.</CheckPayerName>
</Document>

Related

XSLT - add prefix for namespace

Here's my input XML:
<?xml version="1.0" encoding="UTF-8"?>
<Sync
xmlns="http://schema.infor.com/InforOAGIS/2" languageCode="en-US" versionID="2.8.0">
<Data>
<ID>0001</ID>
<Text>ABCD</Text>
</Data>
</Sync>
And here's my expected outcome:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:Sync xmlns:ns0="http://schema.infor.com/InforOAGIS/2"
languageCode="en-US"
versionID="2.8.0">
<DataArea xmlns:dns="http://schema.infor.com/InforOAGIS/2" xmlns="">
<ID>0001</ID>
<Text>ABCD</Text>
</DataArea>
</ns0:Sync>
My current XSLT as below (https://xsltfiddle.liberty-development.net/nbiE19N).
There are 2 problems:
I have the extra xmlns="" in DataArea element. I only want to add the dns namespace.
I cannot add the ns0 prefix for my namespace
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/*:Sync">
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*:Sync/*:Data">
<DataArea>
<xsl:namespace name="dns" select="'http://schema.infor.com/InforOAGIS/2'"/>
<ID>
<xsl:value-of select="/*:Sync/*:Data/*:ID"/>
</ID>
<Text>
<xsl:value-of select="/*:Sync/*:Data/*:Text"/>
</Text>
</DataArea>
</xsl:template>
</xsl:stylesheet>
Any suggestion is appreciated!
Does this return the expected result:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://schema.infor.com/InforOAGIS/2">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/Sync">
<ns0:Sync xmlns:ns0="http://schema.infor.com/InforOAGIS/2">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</ns0:Sync>
</xsl:template>
<xsl:template match="Data">
<DataArea xmlns:dns="http://schema.infor.com/InforOAGIS/2">
<xsl:apply-templates/>
</DataArea>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
P.S. I am not sure why you need the xmlns:dns="http://schema.infor.com/InforOAGIS/2" declaration; it's not being used anywhere.

How to use one cycle for different tags

I have XML with different same tags:
<?xml version="1.0" encoding="UTF-8"?>
<main>
<ROUTES>
<A1_NE>LSN/EMS_XDM_12/1021</A1_NE>
<A2_NE>LSN/EMS_XDM_12/1022</A2_NE>
<Z1_NE>LSN/EMS_XDM_12/1023</Z1_NE>
<Z2_NE>LSN/EMS_XDM_12/1024</Z2_NE>
</ROUTES>
<ROUTES>
<A1_NE>LSN/EMS_XDM_12/1001</A1_NE>
<A2_NE>LSN/EMS_XDM_12/1002</A2_NE>
<A3_NE>LSN/EMS_XDM_12/1003</A3_NE>
<A4_NE>LSN/EMS_XDM_12/1004</A4_NE>
<Z1_NE>LSN/EMS_XDM_12/1005</Z1_NE>
<Z2_NE>LSN/EMS_XDM_12/1006</Z2_NE>
</ROUTES>
</main>
XSLT:
<?xml version="1.1" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="no"/>
<xsl:template match="/">
<MAIN>
<xsl:for-each select="main/ROUTES">
<xsl:element name="ROUTES">
<A_NE><xsl:value-of select="A1_NE"/></A_NE>
<A_NE><xsl:value-of select="A2_NE"/></A_NE>
<A_NE><xsl:value-of select="A3_NE"/></A_NE>
<A_NE><xsl:value-of select="A4_NE"/></A_NE>
<Z_NE><xsl:value-of select="Z1_NE"/></Z_NE>
<Z_NE><xsl:value-of select="Z2_NE"/></Z_NE>
</xsl:element>
</xsl:for-each>
</MAIN>
</xsl:template>
</xsl:stylesheet>
How I can use for-each command to transform A1_NE, A2_NE etc to A_NE column?
And also I've not understand how I can know number of the row in the source xml.
Perhabs xslt version 1.0 couldn't do this transformation.
<?xml version="1.0" encoding="UTF-8"?>
<main>
<ROUTES>
<A_NE>LSN/EMS_XDM_12/1021</A_NE>
<A_NE>LSN/EMS_XDM_12/1022</A_NE>
<Z_NE>LSN/EMS_XDM_12/1023</Z_NE>
<Z_NE>LSN/EMS_XDM_12/1024</Z_NE>
<A_NE>LSN/EMS_XDM_12/1001</A_NE>
<A_NE>LSN/EMS_XDM_12/1002</A_NE>
<A_NE>LSN/EMS_XDM_12/1003</A_NE>
<A_NE>LSN/EMS_XDM_12/1004</A_NE>
<Z_NE>LSN/EMS_XDM_12/1005</Z_NE>
<Z_NE>LSN/EMS_XDM_12/1006</Z_NE>
</ROUTES>
</main>
You should make use of template matching, to change the node names.
First select the child nodes of all ROUTES like so:
<xsl:apply-templates select="main/ROUTES/*" />
Then, have templates like this, for example, to do the renaming
<xsl:template match="A1_NE|A2_NE|A3_NE|A4_NE">
<A_NE><xsl:value-of select="."/></A_NE>
</xsl:template>
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<main>
<ROUTES>
<xsl:apply-templates select="main/ROUTES/*" />
</ROUTES>
</main>
</xsl:template>
<xsl:template match="A1_NE|A2_NE|A3_NE|A4_NE">
<A_NE><xsl:value-of select="."/></A_NE>
</xsl:template>
<xsl:template match="Z1_NE|Z2_NE|Z3_NE|Z4_NE">
<Z_NE><xsl:value-of select="."/></Z_NE>
</xsl:template>
</xsl:stylesheet>
Alternatively, if those are indeed your real element names, you could try and make it generic
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<main>
<ROUTES>
<xsl:apply-templates select="main/ROUTES/*" />
</ROUTES>
</main>
</xsl:template>
<xsl:template match="ROUTES/*">
<xsl:element name="{substring(local-name(), 1, 1)}_{substring-after(local-name(), '_')}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
The logic that needs to be applied is not apparent from the example given. Perhaps all you need to do is:
XSLT 1.0
<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:template match="/main">
<main>
<ROUTES>
<xsl:for-each select="ROUTES/*">
<xsl:element name="{translate(name(), '1234567890', '')}">
<xsl:value-of select="." />
</xsl:element>
</xsl:for-each>
</ROUTES>
</main>
</xsl:template>
</xsl:stylesheet>

Facing Issue in XSLT Format

I am looking my xslt in below format:
<xml>
<apis>
<name>API Name</name>
<comment> Comment</comment>
<version>12</version>
</apis>
</xml>
XSLT Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:L7j="http://ns.l7tech.com/2012/08/jdbc-query-result" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<xml>
<xsl:apply-templates select="//L7j:col" />
</xml>
</xsl:template>
<xsl:template match="//L7j:col">
<api>
<xsl:element name="{#name}">
<xsl:value-of select="." /></xsl:element>
</api>
</xsl:template>
</xsl:stylesheet>
Input XML:
<?xml version="1.0" encoding="UTF-8"?>
<L7j:jdbcQueryResult xmlns:L7j="http://ns.l7tech.com/2012/08/jdbc-query-result">
<L7j:row>
<L7j:col name="name" type="java.lang.String">Policy for service #0b8bab6913cc588557b6973e94d1bfdd, WSTrustSoapService</L7j:col>
<L7j:col name="comment">
<![CDATA[NULL]]>
</L7j:col>
<L7j:col name="version" type="java.lang.Integer">18</L7j:col>
</L7j:row>
<L7j:row>
<L7j:col name="name" type="java.lang.String">Policy for service #0b8bab6913cc588557b6973e94d5893d, UUPRStub</L7j:col>
<L7j:col name="comment">
<![CDATA[NULL]]>
</L7j:col>
<L7j:col name="version" type="java.lang.Integer">16</L7j:col>
</L7j:row>
</L7j:jdbcQueryResult>
If I understand correctly, you want to do:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:L7j="http://ns.l7tech.com/2012/08/jdbc-query-result"
exclude-result-prefixes="L7j">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="/L7j:jdbcQueryResult">
<xml>
<xsl:apply-templates/>
</xml>
</xsl:template>
<xsl:template match="L7j:row">
<apis>
<xsl:apply-templates/>
</apis>
</xsl:template>
<xsl:template match="L7j:col">
<xsl:element name="{#name}">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
</xsl:stylesheet>

Moving and renaming contents of an XML node

i am a newbie when it comes to XSLT translations, and have been searching with this question for a while, but did not find any answher to it. I have an XML file looking like this:
<item>
<code>I001</code>
<description>DEF</description>
<properties>
<line1>
<key>key 1</key>
<value>value 1</value>
</line1>
<line2>
<key>key 2</key>
<value>value 2</value>
</line2>
</properties>
</item>
The label-software that i need to process this data with does not cope with this kind of leveled xml, so i have to transform it to something like this
<?xml version="1.0" encoding="utf-8"?>
<item>
<code>I001</code>
<description>DEF</description>
<P1_key>key 1</P1_key>
<P1_value>value 1</P1_value>
<P2_key>key 1</P2_key>
<P2_value>value</P2_value>
</item>
So far i have come up with an xsl-file that looks like this:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<!-- Identity rule -->
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<!-- special rules ... -->
<xsl:template match="properties/line1/*">
<xsl:element name="P1_{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="properties/line2/*">
<xsl:element name="P2_{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
This does only partly what i need (renaming the elements), wit a result looking like this:
<?xml version="1.0" encoding="utf-8"?>
<item>
<code>I001</code>
<description>DEF</description>
<properties>
<line1>
<P1_key>key 1</P1_key>
<P1_value>value 1</P1_value>
</line1>
<line2>
<P2_key>key 1</P2_key>
<P2_value>value</P2_value>
</line2>
</properties>
</item>
What i now would like to now is how to move the renamed elements (P1_key, P1_value, P2_key, P2_value) to the level.
Any hints would be appreciated.
Thanks
How about:
XSLT 1.0
<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:template match="/item">
<xsl:copy>
<xsl:copy-of select="code | description"/>
<xsl:for-each select="properties/*/key">
<xsl:element name="P{position()}_key">
<xsl:value-of select="."/>
</xsl:element>
<xsl:element name="P{position()}_value">
<xsl:value-of select="following-sibling::value[1]"/>
</xsl:element>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Or perhaps:
<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:template match="/item">
<xsl:copy>
<xsl:copy-of select="code | description"/>
<xsl:for-each select="properties/*/key">
<xsl:variable name="line-num" select="substring-after(name(..), 'line')" />
<xsl:element name="P{$line-num}_key">
<xsl:value-of select="."/>
</xsl:element>
<xsl:element name="P{$line-num}_value">
<xsl:value-of select="following-sibling::value[1]"/>
</xsl:element>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Of course, if there always will be exactly two lines, you could just spell it out:
<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:template match="/item">
<xsl:copy>
<xsl:copy-of select="code | description"/>
<P1_key>
<xsl:value-of select="properties/line1/key" />
</P1_key>
<P1_value>
<xsl:value-of select="properties/line1/value" />
</P1_value>
<P2_key>
<xsl:value-of select="properties/line2/key" />
</P2_key>
<P2_value>
<xsl:value-of select="properties/line2/value" />
</P2_value>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
BTW, your method could work too, if you add another template:
<xsl:template match="properties | line1 | line2">
<xsl:apply-templates />
</xsl:template>

get the xml attribute value using xslt tree wise

This is my xml file:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="try.xsl"?>
<oneday>
<team1 id="1" team="India">
<team2 id="2" team="gujarat">
<team3 id="3" team="guj11"></team3>
</team2>
</team1>
</oneday>
This is my xsl file:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:output method="text" />
<xsl:template match="*">
<xsl:value-of select="local-name()"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()[normalize-space(.)]">
<xsl:value-of select="concat(':', .)"/>
</xsl:template>
</xsl:stylesheet>
This is my output:
oneday
team1
team2
team3
But I want to output something like this:
oneday
team1:India
team2:Gujarat
team3:Guj11
How's this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="*">
<xsl:apply-templates select="ancestor::*" mode="spacing" />
<xsl:value-of select="local-name()"/>
<xsl:if test="#team">
<xsl:value-of select="concat(':', #team)"/>
</xsl:if>
<xsl:text>
</xsl:text>
<xsl:apply-templates select="*" />
</xsl:template>
<xsl:template match="*" mode="spacing">
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
When run on your sample XML, this produces:
oneday
team1:India
team2:gujarat
team3:guj11
When run on a slightly more complex XML:
<oneday>
<team1 id="1" team="India">
<team2 id="2" team="gujarat">
<team3 id="3" team="guj11"></team3>
</team2>
<team6 team="Mumbai" />
</team1>
<team4 team="France">
<team5 team="Paris" />
</team4>
</oneday>
It produces:
oneday
team1:India
team2:gujarat
team3:guj11
team6:Mumbai
team4:France
team5:Paris