XSL rename element name but namespace in the wrong place - xslt

I have an xml and i want to rename/changes the element name and leave everthing unchanges but i facing the unexpected result.
Incoming XML
<?xml version="1.0" encoding="utf-8"?>
<PublishVENDOR baseLanguage="EN" messageID="507085.1468382418796837538" event="1" xmlns="http://store/companies" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<VENDORSet>
<COMPANIES action="Replace">
<ADDRESS1>32 SUMNER STREET</ADDRESS1>
<ADDRESS2>HARTFORD</ADDRESS2>
<ADDRESS3>CT</ADDRESS3>
<ADDRESS4>03342</ADDRESS4>
</COMPANIES>
</VENDORSet>
</PublishVENDOR>
XSL Map
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://store/companies" version="1.0">
<xsl:template match="/ns:PublishVENDOR">
<xsl:element name="SyncVENDOR">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
The result
<?xml version="1.0" encoding="utf-8"?>
<SyncMXVENDOR baseLanguage="EN" messageID="507085.1468382418796837538" event="1">
<VENDORSet xmlns="http://www.ibm.com/maximo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<COMPANIES action="Replace">
<ADDRESS1>32 SUMNER STREET</ADDRESS1>
<ADDRESS2>HARTFORD</ADDRESS2>
<ADDRESS3>CT</ADDRESS3>
<ADDRESS4>03342</ADDRESS4>
</COMPANIES>
</VENDORSet>
</SyncVENDOR>
The result that i want is
<?xml version="1.0" encoding="utf-8"?>
<SyncVENDOR baseLanguage="EN" messageID="507085.1468382418796837538" event="1" xmlns="http://store/companies" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<VENDORSet>
<COMPANIES action="Replace">
<ADDRESS1>32 SUMNER STREET</ADDRESS1>
<ADDRESS2>HARTFORD</ADDRESS2>
<ADDRESS3>CT</ADDRESS3>
<ADDRESS4>03342</ADDRESS4>
</COMPANIES>
</VENDORSet>
</SyncVENDOR>
Please somebody help me... and i'm sorry that my english is not good too

Change
<xsl:template match="/ns:PublishVENDOR">
<xsl:element name="SyncVENDOR">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
to
<xsl:template match="/ns:PublishVENDOR">
<SyncVENDOR xmlns="http://store/companies">
<xsl:copy-of select="namespace::*"/>
<xsl:apply-templates select="#*|node()"/>
</SyncVENDOR>
</xsl:template>

Related

How to remove a specific prefix using XSLT

I need to remove the ns0: prefix from the RecuperarCopiaResult node.
From <ns0:RecuperarCopiaResult> to <RecuperarCopiaResult>
Follows Input XML
<?xml version="1.0" encoding="UTF-8"?>
<ns0:RecuperarCopiaResponse xmlns:ns0="http://tempuri.org/">
<ns0:RecuperarCopiaResult><![CDATA[<Abastecimento_NF
ULTIMO_PONTEIRO="447050"><Abastecimento_NFRow><DT_PROCESS>6/2/2018
1:46:08</DT_PROCESS><CD_ABASTECIMENTO>123936138</CD_ABASTECIMENTO>
<CD_VEICULO>479077</CD_VEICULO><CD_TIPO_REGISTRO>1</CD_TIPO_REGISTRO>
<NR_BANCO>237</NR_BANCO><CD_REDE>801</CD_REDE><DC_REDE>801</DC_REDE>
<COD_POSTO>244</COD_POSTO><COD_FROTA>4941</COD_FROTA>
<COD_SUBFROTA>11264</COD_SUBFROTA><DC_SUBFROTA>R2C</DC_SUBFROTA>
<CD_COMBUSTIVEL>S</CD_COMBUSTIVEL><DC_COMBUSTIVEL>S</DC_COMBUSTIVEL>
<NR_UVE></NR_UVE><DC_PLACA>KWG8687</DC_PLACA><NM_MOTORISTA>
</NM_MOTORISTA><NR_KM_ATUAL>226076</NR_KM_ATUAL>
<NR_QTD_LITROS>139,55</NR_QTD_LITROS>
<NR_QTD_LITROS_TOTAL>139,55</NR_QTD_LITROS_TOTAL>
<CD_STATUS_ABASTECIMENTO>S</CD_STATUS_ABASTECIMENTO>
</Abastecimento_NFRow></Abastecimento_NF>]]></ns0:RecuperarCopiaResult>
</ns0:RecuperarCopiaResponse>
I am using the following xslt code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:SOAP-
ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://tempuri.org/">
<xsl:output encoding='UTF-8' method="xml" indent="yes" omit-xml-
declaration="yes" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="SOAP-ENV:*">
<xsl:apply-templates select="#* | node()"/>
</xsl:template>
<xsl:template match="ns0:*">
<xsl:element name="ns0:{local-name()}"
namespace="http://www.supergasbras.com.br/service/CtfAbastecimento">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="." disable-output-escaping="yes"/>
</xsl:template>
</xsl:stylesheet>
Following is the expected XML:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:RecuperarCopiaResponse
xmlns:ns0="http://www.supergasbras.com.br/service/CtfAbastecimento">
<RecuperarCopiaResult>
<Abastecimento_NF ULTIMO_PONTEIRO="447050">
<Abastecimento_NFRow>
<DT_PROCESS>6/2/2018 1:46:08</DT_PROCESS>
<CD_ABASTECIMENTO>123936138</CD_ABASTECIMENTO>
<CD_VEICULO>479077</CD_VEICULO>
<CD_TIPO_REGISTRO>1</CD_TIPO_REGISTRO>
<NR_BANCO>237</NR_BANCO>
<CD_REDE>801</CD_REDE>
<DC_REDE>801</DC_REDE>
<COD_POSTO>244</COD_POSTO>
<COD_FROTA>4941</COD_FROTA>
<COD_SUBFROTA>11264</COD_SUBFROTA>
<DC_SUBFROTA>R2C</DC_SUBFROTA>
<CD_COMBUSTIVEL>S</CD_COMBUSTIVEL>
<DC_COMBUSTIVEL>S</DC_COMBUSTIVEL>
<NR_UVE/>
<DC_PLACA>KWG8687</DC_PLACA>
<NM_MOTORISTA/>
<NR_KM_ATUAL>226076</NR_KM_ATUAL>
<NR_QTD_LITROS>139,55</NR_QTD_LITROS>
<VL_PRECO_UNITARIO>3,798</VL_PRECO_UNITARIO>
<VL_PRECO_AEP>3,798</VL_PRECO_AEP>
<VL_VALOR_TOTAL>530,01</VL_VALOR_TOTAL>
<DT_EVENTO>5/2/2018 14:37:00</DT_EVENTO>
<DT_DEBITO>26/2/2018 0:00:00</DT_DEBITO>
<DT_CREDITO>27/2/2018 0:00:00</DT_CREDITO>
<NOMEARQ>T2060218.ZZ001305.00244</NOMEARQ>
<NR_KM_PERCORRIDA>365</NR_KM_PERCORRIDA>
<NR_QTD_LITROS_TOTAL>139,55</NR_QTD_LITROS_TOTAL>
<CD_STATUS_ABASTECIMENTO>S</CD_STATUS_ABASTECIMENTO>
</Abastecimento_NFRow>
</Abastecimento_NF>
</RecuperarCopiaResult>
</ns0:RecuperarCopiaResponse>
Your question says one thing, your expected result shows something quite different. Try it this way:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tmp="http://tempuri.org/"
exclude-result-prefixes="tmp">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/tmp:RecuperarCopiaResponse">
<ns0:RecuperarCopiaResponse xmlns:ns0="http://www.supergasbras.com.br/service/CtfAbastecimento">
<xsl:apply-templates/>
</ns0:RecuperarCopiaResponse>
</xsl:template>
<xsl:template match="tmp:RecuperarCopiaResult">
<RecuperarCopiaResult>
<xsl:value-of select="." disable-output-escaping="yes"/>
</RecuperarCopiaResult>
</xsl:template>
</xsl:stylesheet>

XSLT add root node if not exists

I have some XML and having a difficult time transforming it.
Example XML:
<?xml version="1.0" encoding="utf-8"?>
<Cars xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Car> ... </Car>
</Cars>
I would like to change it to:
<?xml version="1.0" encoding="utf-8"?>
<Depot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Cars>
<Car> ... </Car>
</Cars>
</Depot>
Sounds simple enough but the problem is some data is already in the expected format, in which case I don't want to apply the transform. How do I achieve this?
EDIT
Some starting XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" mlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Cars">
<Depot>
<Cars>
<xsl:apply-templates select="*"/>
</Cars>
</Depot>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I think you only want to match Cars if it is the root element, so instead of your template matching "Cars", change it to match "/Cars"
<xsl:template match="/Cars">
Try this XSLT (which I have slightly amended to get the first template to call the identity template)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsl:output method="xml" indent="yes" />
<xsl:template match="/Cars">
<Depot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsl:call-template name="identity" />
</Depot>
</xsl:template>
<xsl:template match="#*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I think that it is just necessary to use a choose in the root template to test if the node Depot exists, if not create it:
<xsl:template match="/">
<xsl:choose>
<xsl:when test="Depot">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<Depot>
<xsl:apply-templates/>
</Depot>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
This also gives same output.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsl:template match="Cars">
<Depot>
<xsl:copy-of select="."/>
</Depot>
</xsl:template>
</xsl:stylesheet>

Replace strings XSLT

i'm stucked. Please help me with a little problem.
I have to change just two specific lines in XML file like this:
<?xml version="1.0" encoding="UTF-8"?>
<max:PublishTP_WORKORDER xmlns:max="http://www.ibm.com/maximo" creationDateTime="2014-04-11T10:43:51+04:00" transLanguage="RU" baseLanguage="EN" messageID="1397198631936413520" maximoVersion="7 5 20130829-1209 V7510--1" event="1">
<TP_WORKORDERSet xmlns="http://www.ibm.com/maximo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<WORKORDER action="Replace">
<ACTCOST xsi:nil="true"/>
<ACTFINISH xsi:nil="true"/>
<ACTINTLABCOST>0.0</ACTINTLABCOST>
<ACTINTLABHRS>0.0</ACTINTLABHRS>
<ACTLABCOST>0.0</ACTLABCOST>
<ACTLABHRS>0.0</ACTLABHRS>
<ACTMATCOST>0.0</ACTMATCOST>
<ACTOUTLABCOST>0.0</ACTOUTLABCOST>
<ACTOUTLABHRS>0.0</ACTOUTLABHRS>
<ACTSERVCOST>0.0</ACTSERVCOST>
<ACTSTART>2013-11-08T12:03:26+04:00</ACTSTART>
<ACTTOOLCOST>0.0</ACTTOOLCOST>
<ADDRESS/>
<AMCREW/>
<AMS>0</AMS>
<AOS>0</AOS>
...........................
<WORKORDERID>10</WORKORDERID>
<WORKPACKMTLSTATUS/>
<WORKTYPE/>
<WOSEQUENCE xsi:nil="true"/>
</WORKORDER>
</TP_WORKORDERSet>
</max:PublishTP_WORKORDER>
I need to replace "PublishTP_WORKORDER" with "Create_WORKORDER", both open and close tags.
It works fine with:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:max="http://www.ibm.com/maximo" version="1.0">
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/max:PublishTP_WORKORDER">
<xsl:element name="max:CreateTP_WORKORDER">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
But in XML file it could be "PublishTP_WORKORDER2" or "PublishTP_WORKORDER3" and so on.
It should be changed to "CreateTP_WORKORDER2", "CreateTP_WORKORDER3" etc
And this XSLT scheme stops working. It's just doesn't recognize strings with added numeric symbols. How could i turn it out? Thanks in advance.
It's always root element
Then how about:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:max="http://www.ibm.com/maximo">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:variable name="suffix" select="substring-after(local-name(), 'PublishTP_WORKORDER')" />
<xsl:element name="max:CreateTP_WORKORDER{$suffix}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

how to remove a part of attribut to a node in xml file using xslt

I have the following xml code:
<OML>
<bg-def xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="EX1"/>
</OML>
I want to remove the attribute xmlns:xsi and its value using XSLT, so that the result will look like this:
<OML>
<bg-def name="EX1"/>
</OML>
I tryied to do this with the following XSLT code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:ex="http://exslt.org/dates-and-times" extension-element-prefixes="ex">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no" xml:space="preserve"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="bg-def|# xmlns:xsi"/>
</xsl:transform>
Before I finished to write my code, my editor warned me that:
"W Namespace prefix xmlns has not been declared".
When I remove the expression :xsi and just write xmlns, there is no warning more. But when I compile and execute my program, nothing happens and I don't get the expected output.
I try also to change the last line of my xslt file with this:
<xsl:template match="bg-def|# name"/>
then the result is looking like this:
<OML>
<bg-def xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</OML>
That means, the attribute name has been removed very well. But I want to do this with the attribute xmlns:xsi.
Can someone help me to do this please?
Thanks for any help.
Franky
Use following template for bd-def node:
<xsl:template match="bg-def">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="node()|#*"/>
</xsl:element>
</xsl:template>
Instead of
<xsl:template match="bg-def|# name"/>
This template will create node bg-def and copy all it context nodes and attributes, but not namespaces
Check similar question:
remove namespace for a perticular element
Update:
Source file:
<OML>
<bg-def xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="EX1"/>
</OML>
Stylesheet:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:ex="http://exslt.org/dates-and-times" extension-element-prefixes="ex">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no" xml:space="preserve"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="bg-def">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="node()|#*"/>
</xsl:element>
</xsl:template>
</xsl:transform>
Transformation result (Saxon 6.5.5 - Xslt 1.0):
<?xml version="1.0" encoding="UTF-8"?><OML>
<bg-def name="EX1"/>
</OML>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>

xsl attribute namespace

I have the following xml
<?xml version="1.0" encoding="UTF-8"?>
<content>
<artwork classification="12" href="1.jpg"/>
<artwork classification="10" href="2.jpg"/>
</content>
When applying the xsl
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#href">
<xsl:attribute name="xlink:href">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
it produces
<?xml version="1.0" encoding="UTF-8"?>
<content>
<artwork classification="12" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="1.jpg"/>
<artwork classification="10" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="2.jpg"/>
</content>
whereas I need
<?xml version="1.0" encoding="UTF-8"?>
<content xmlns:xlink="http://www.w3.org/1999/xlink">
<artwork classification="12" xlink:href="1.jpg"/>
<artwork classification="10" xlink:href="2.jpg"/>
</content>
How should I modify my xsl to get the result I need?
I use xalan XSLT processor.
You need just to match the elements for which you want the namespace declared. The processor will apply the namespace for you.
XSLT 1.0 tested under MSXSL 4.0 (and also tested as XSLT 2.0 under Saxon-HE 9.2.1.1J)
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="content">
<content>
<xsl:apply-templates select="#*|node()"/>
</content>
</xsl:template>
<xsl:template match="#href">
<xsl:attribute name="xlink:href">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>