how to remove name spaces in xslt 1.0 - xslt

input:
<?xml version="1.0" encoding="UTF-8" ?><DocumentCombined xmlns="http://xmlns.oracle.com/pcbpel/schema/ACCO_EDI_X12_Scheduledjobs/Write_867xmlfile">
<Header xmlns="">
<ISADATE>
<value-of/>
</ISADATE>
</Header>
</DocumentCombined>
here i need to remove the xmlns name spaces to the DocumentCombined element and Header elements.
output:
<?xml version="1.0">
<DocumentCombined>
<Header>
<ISADATE>
<value-of/>
</ISADATE>
</Header>
</DocumentCombined>

If you want to strip all namespaces simply use
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>

Related

XSLT. How to do 2 changes for 1 element? Ordering and renaming

I need to change order of elements. But also rename elements into elements.
So,
I have xml:
<transactionality>
<rollbackexttransactionid>
<rollbackvalidity>3600</rollbackvalidity>
<rollbackscheduledattemps>3</rollbackscheduledattemps>
<manualcorrectionpath>TransactionalityLogs</manualcorrectionpath>
</rollbackexttransactionid>
<transactionalitylogspath>TransactionalityLogs</transactionalitylogspath>
<rollbacklifecycleevents>
<rollbacklifecycle>1200</rollbacklifecycle>
<rollbackscheduledattemps>2</rollbackscheduledattemps>
<manualcorrectionpath>TransactionalityLogs</manualcorrectionpath>
</rollbacklifecycleevents>
<rollbackpayment>
<rollbackvalidity>1200</rollbackvalidity>
<rollbackscheduledattemps>2</rollbackscheduledattemps>
<manualcorrectionpath>TransactionalityLogs</manualcorrectionpath>
</rollbackpayment>
</transactionality>
I need to do element transactionalitylogspath as first in to transactionality.
Rename all elements "rollbackscheduledattemps" to "rollbackscheduledattempts"
Rename rollbacklifecycleevents/rollbacklifecycle to rollbacklifecycleevents/rollbackvalidity
I would'like to have:
<transactionality>
<transactionalitylogspath>TransactionalityLogs</transactionalitylogspath>
<rollbackexttransactionid>
<rollbackvalidity>3600</rollbackvalidity>
<rollbackscheduledattempts>3</rollbackscheduledattempts>
<manualcorrectionpath>TransactionalityLogs</manualcorrectionpath>
</rollbackexttransactionid>
<rollbacklifecycleevents>
<rollbackvalidity>1200</rollbackvalidity>
<rollbackscheduledattempts>2</rollbackscheduledattempts>
<manualcorrectionpath>TransactionalityLogs</manualcorrectionpath>
</rollbacklifecycleevents>
<rollbackpayment>
<rollbackvalidity>1200</rollbackvalidity>
<rollbackscheduledattempts>2</rollbackscheduledattempts>
<manualcorrectionpath>TransactionalityLogs</manualcorrectionpath>
</rollbackpayment>
</transactionality>
I did:
<xsl:template match="transactionality">
<xsl:variable name="elements-after" select="rollbackexttransactionid|rollbacklifecycleevents|rollbackpayment"/>
<xsl:copy>
<xsl:copy-of select="transactionalitylogspath"/>
<xsl:copy-of select="$elements-after">
</xsl:copy-of >
</xsl:copy>
</xsl:template>
<xsl:template match="rollbackscheduledattemps">
<rollbackscheduledattempts>
<xsl:apply-templates select="#* | node()"/>
</rollbackscheduledattempts>
</xsl:template>
byt it doesn't work :(.
Help me please.
Here's how I would do it :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="transactionality">
<xsl:copy>
<xsl:apply-templates select="transactionalitylogspath"/>
<xsl:apply-templates select="*[local-name() != 'transactionalitylogspath']"/>
</xsl:copy>
</xsl:template>
<xsl:template match="rollbackscheduledattemps">
<rollbackscheduledattempts>
<xsl:value-of select="."/>
</rollbackscheduledattempts>
</xsl:template>
<xsl:template match="rollbacklifecycleevents/rollbacklifecycle">
<rollbackvalidity>
<xsl:value-of select="."/>
</rollbackvalidity>
</xsl:template>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Here's a working example : https://xsltfiddle.liberty-development.net/6pS26mL

How to use variable in template match xslt

I need to use variable in template match in xslt but I transformed template match into variable. I got syntax error.
This is my orginal xslt
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/name/name[not(telephoneNav/detail/action = 'A') and not(telephoneNav/detail/action = 'S')]"/>
<xsl:template match="detail[not(action = 'A') and not(action = 'S')]"/>
</xsl:stylesheet>
This is my xslt which has been transformed into variable in template match.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:variable name="actionXpath1" select="'/name/name[not(telephoneNav/detail/action = &apos;A&apos;) and not(telephoneNav/detail/action = &apos;S&apos;)]'" />
<xsl:variable name="actionXpath2" select="'detail[not(action = &apos;A&apos;) and not(action = &apos;S&apos;)]'" />
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="$actionXpath1"/>
<xsl:template match="$actionXpath2"/>
</xsl:stylesheet>
like this https://xsltfiddle.liberty-development.net/3MvmXiw
In XSLT 3 using static parameters and _match as a shadow attribute you can use
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:param name="actionXpath1" static="yes" select="'/name/name[not(telephoneNav/detail/action = "A") and not(telephoneNav/detail/action = "S")]'" />
<xsl:param name="actionXpath2" static="yes" select="'detail[not(action = "A") and not(action = "S")]'" />
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template _match="{$actionXpath1}"/>
<xsl:template _match="{$actionXpath2}"/>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/3MvmXiw/1
So you need to use an XSLT 3 processor and you need to use it in a way that allows setting static parameters, i.e. use an API specialized for XSLT 3 to support setting such parameters before the stylesheet is compiled.

XSL code to rename the prefix without disturbing the attributes

I have given below the XSL codes i have tried and the part of input and output codes.If I use XSL1 to rename the namespace prefix values in the xml tags , unfortunately it collapses the attribute values and if I use XSL2 attributes are getting created a separate nodes. Can someone pls help to write an XSL to rename the prefixes but to keep the attributes in the same node.
XSL 1:​
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns0:*">
<xsl:element name="ubl:{local-name()}" namespace="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
XSL2:
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy></xsl:template>
<xsl:template match="#*">
<xsl:element name="{name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
<xsl:template match="ns0:*">
<xsl:element name="ubl:{local-name()}" namespace="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
Input:
<ns5:LegalMonetaryTotal>
<ns2:LineExtensionAmount currencyID="EUR">35.38</ns2:LineExtensionAmount>
<ns2:TaxExclusiveAmount currencyID="EUR">35.38</ns2:TaxExclusiveAmount>
<ns2:TaxInclusiveAmount currencyID="EUR">37.5</ns2:TaxInclusiveAmount>
<ns2:PrepaidAmount currencyID="EUR">37.5</ns2:PrepaidAmount>
<ns2:PayableAmount currencyID="EUR">0.00</ns2:PayableAmount>
</ns5:LegalMonetaryTotal>
Output1:
<cac:LegalMonetaryTotal >
<cbc:LineExtensionAmount >EUR35.38</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount >EUR35.38</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount >EUR37.5</cbc:TaxInclusiveAmount>
<cbc:PrepaidAmount >EUR37.5</cbc:PrepaidAmount>
<cbc:PayableAmount >EUR0.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
Output2:
<cac:LegalMonetaryTotal >
<cbc:LineExtensionAmount >
<currencyID>EUR</currencyID>
35.38
</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount >
<currencyID>EUR</currencyID>
35.38
</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount >
<currencyID>EUR</currencyID>
37.5
</cbc:TaxInclusiveAmount>
<cbc:PrepaidAmount >
<currencyID>EUR</currencyID>
37.5
</cbc:PrepaidAmount>
<cbc:PayableAmount>
<currencyID>EUR</currencyID>
0.00
</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
But Expected output is: I have tried multiple options guys. Please help me to get the below format.
<cbc:LegalMonetaryTotal>
<cac:LineExtensionAmount currencyID="EUR">35.38</cac:LineExtensionAmount>
<cac:TaxExclusiveAmount currencyID="EUR">35.38</cac:TaxExclusiveAmount>
<cac:TaxInclusiveAmount currencyID="EUR">37.5</cac:TaxInclusiveAmount>
<cac:PrepaidAmount currencyID="EUR">37.5</cac:PrepaidAmount>
<cac:PayableAmount currencyID="EUR">0.00</cac:PayableAmount>
</cbc:LegalMonetaryTotal>
Regards,
Indu
The reason why your first stylesheet does not output any attributes is that you have no template that handles attributes. Therefore, the instruction:
<xsl:apply-templates select="#* | node()"/>
does not do anything for attributes.
Try changing your first template:
<xsl:template match="/">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
to the standard identity transform template:
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
That will probably make it work. I say probably, because your stylesheet does not fit your input nor the expected output. Your stylesheet looks for:
<xsl:template match="ns0:*">
but your input has no elements with a ns0 prefix. And your stylesheet outputs a ubl prefix, while your expected output uses cbc and cac prefixes. And - as already mentioned in the comments to your question - all these prefixes need to be bound to namespaces in order for the input and the input to be well-formed XML documents.

XSLT convert xml block under a specific node to xml-escaped content of that node

Any ideas of how the following problem can be solved would be highly appreciated.
INPUT:
<p>
<div>
Original<br/>This is the original <b>acid</b>, a hydroxy monocarboxylic <span class="hl1">acid</span>.
</div>
</p>
Desired Output:
<p>
<div>
Original<br/>This is the original <b>acid</b>, a hydroxy monocarboxylic <span class="hl1">acid</span>.
</div>
</p>
Attempt 1:
`<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output omit-xml-declaration="yes" indent="no" encoding="UTF-8"/>
<!--The identity template -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="div">
<xsl:copy>
<xsl:value-of select="/" disable-output-escaping="no"/>
</xsl:copy>
</xsl:template>
`
Attempt2:
as an alternative, I thought of placing the child elements' content into a CDATA wrapper.
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output omit-xml-declaration="yes" indent="no" encoding="UTF-8"/>
<!--The identity template -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="div">
<xsl:copy>
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:value-of select="/" />
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:copy>
</xsl:template>
But that does not give me what I want.
Anyone with a better idea? I'm using XSLT 2.0
Here is a suggestion using XSLT 3.0 serialize() as supported by Saxon 9.6 HE, PE and EE:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="div">
<xsl:copy>
<xsl:apply-templates mode="serialize"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()" mode="serialize">
<xsl:variable name="ser-params">
<output:serialization-parameters xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
<output:omit-xml-declaration value="yes"/>
</output:serialization-parameters>
</xsl:variable>
<xsl:value-of select="serialize(., $ser-params/*)"/>
</xsl:template>
</xsl:stylesheet>
With older version of Saxon 9 you could use the extension function serialize, as shown in http://xsltransform.net/pPqsHTx:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output name="inline" omit-xml-declaration="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="div">
<xsl:copy>
<xsl:apply-templates mode="serialize"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()" mode="serialize">
<xsl:value-of xmlns:saxon="http://saxon.sf.net/" select="saxon:serialize(., 'inline')"/>
</xsl:template>
</xsl:stylesheet>
Your second attempt should work if you change your xsl:value-of to an xsl:copy-of and tweak the select:
<xsl:template match="div">
<xsl:copy>
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:copy-of select="node()" />
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:copy>
</xsl:template>

How to group neighbour-siblings

i have something like this:
<root>
<a>foo</a>
<b>bar</b>
<groupme>foobar</groupme>
<groupme>baz</groupme>
<groupme>42</groupme>
<c>abc</c>
<d>def</d>
<groupme>foo</groupme>
<x>xyz</x>
<groupme>bar</groupme>
<groupme>foo</groupme>
<z>thats it</z>
</root>
now i need all groume's which are direct neighbours to be a single node like:
<root>
<a>foo</a>
<b>bar</b>
<groupme>foobar baz 42</groupme>
<c>abc</c>
<d>def</d>
<groupme>foo</groupme>
<x>xyz</x>
<groupme>bar foo</groupme>
<z>thats it</z>
</root>
also the groupme nodes containing other nodes, i've just leave them to provide a simple example.
the groupme nodes only apear in a specific level, no groupme nodes in others then root.
any help for me?
Such grouping can be achieved with an approach called "sibling recursion", for your problem I would suggest a stylesheet as follows:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root/groupme[not(preceding-sibling::*[1][self::groupme])]">
<xsl:copy>
<xsl:apply-templates select="node()"/>
<xsl:apply-templates select="following-sibling::*[1][self::groupme][1]" mode="list"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root/groupme[preceding-sibling::*[1][self::groupme]]"/>
<xsl:template match="root/groupme[preceding-sibling::*[1][self::groupme]]" mode="list">
<xsl:text> </xsl:text>
<xsl:apply-templates select="node()"/>
<xsl:apply-templates select="following-sibling::*[1][self::groupme][1]" mode="list"/>
</xsl:template>
</xsl:stylesheet>
When applied to the input
<root>
<a>foo</a>
<b>bar</b>
<groupme>foobar</groupme>
<groupme>baz</groupme>
<groupme>42</groupme>
<c>abc</c>
<d>def</d>
<groupme>foo</groupme>
<x>xyz</x>
<groupme>bar</groupme>
<groupme>foo</groupme>
<z>thats it</z>
</root>
the result is
<root>
<a>foo</a>
<b>bar</b>
<groupme>foobar baz 42</groupme>
<c>abc</c>
<d>def</d>
<groupme>foo</groupme>
<x>xyz</x>
<groupme>bar foo</groupme>
<z>thats it</z>
</root>
As an alternative to the sibling recursion it is also possible to "grab" the following siblings with a key based approach:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:key
name="first"
match="root/groupme[preceding-sibling::*[1][self::groupme]]"
use="generate-id(preceding-sibling::groupme[not(preceding-sibling::*[1][self::groupme])][1])"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root/groupme[not(preceding-sibling::*[1][self::groupme])]">
<xsl:copy>
<xsl:apply-templates select="node()"/>
<xsl:apply-templates select="key('first', generate-id())" mode="list"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root/groupme[preceding-sibling::*[1][self::groupme]]"/>
<xsl:template match="root/groupme" mode="list">
<xsl:text> </xsl:text>
<xsl:apply-templates select="node()"/>
</xsl:template>
</xsl:stylesheet>