xsl attribute namespace - xslt

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>

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 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>

XSL rename element name but namespace in the wrong place

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>

XSLT transformation : Transfer only 1 of the namespaces

I am new to XSLT transformation and cant seem to get the following result
I have:
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.002.001.03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.002.001.03 pain.002.001.03.xsd">
<CstmrPmtStsRpt>
need this:
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.002.001.03">
<CstmrPmtStsRpt>
Where the rest of the document should remain the same.
I have put together the following XSLT:
<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output indent="yes" method="xml" encoding="utf-8" />
<!-- template to copy elements -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="#xsi:schemaLocation">
</xsl:template>
<!-- template to copy attributes -->
<xsl:template match="#*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<!-- template to copy the rest of the nodes -->
<xsl:template match="comment() | text() | processing-instruction()">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
but get this
<?xml version="1.0" encoding="utf-8"?>
<Document>
<CstmrPmtStsRpt>
Any tips would be appreciated.