ignore node using XSLT - node.js

I have below xml file which is coming form my vendor.
<?xml version="1.0" encoding="UTF-8"?>
<nm:MT_employee xmlns:nm="http://firstscenario.com"xmlns:tl="http://secondscenario.com">
<EMployeeDetails>
<Name>Janardhan</Name>
<id>1234</id>
<Address>India</Address>
</EMployeeDetails>
<tl:Extension>
<tl:Number>5678</tl:Number>
<tl:Salary>2345678</tl:Salary>
</tl:Extension>
</nm:MT_employee>
In the above xml I want to ignore the entire tl:Extension node. the final output should be like below
<?xml version="1.0" encoding="UTF-8"?>
<nm:MT_employee xmlns:nm="http://firstscenario.com"xmlns:tl="http://secondscenario.com">
<EMployeeDetails>
<Name>Janardhan</Name>
<id>1234</id>
<Address>India</Address>
</EMployeeDetails>
</nm:MT_employee>
I tried to with different XSLT codes but it's not working. Could you please suggest how can I achieve this?
Regards,
Janardhan

The general rule to "ignore" an element from the source XML
is to write an "empty" template for this element, in your case:
<xsl:template match="tl:Extension"/>
As this template refers to tl namespace, it must be specified
in the xsl:transform tag.
Of course, to copy the rest of the source content, your script
must include the identity template.
Below you have an example script:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tl="http://secondscenario.com" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="tl:Extension"/>
<xsl:template match="#*|node()">
<xsl:copy><xsl:apply-templates select="#*|node()"/></xsl:copy>
</xsl:template>
</xsl:transform>

Related

How to map repeating xml elements in Excel

I'm dealing with a problem on how to map repeating xml elements, the moment I imported the XML below as an XML map in excel, I see only 1 for the 4 records i need "<club_LIST>" of course this doesn't produce the 4 entries in the output XML.
Any idea how can this be solved in Excel ?
I from Microsoft support:
Additionally, the contents of an XML mapping cannot be exported if the contents contain one of the following XML schema constructs:
List of lists One list of items contains a second list of items.
Any way around you could suggest to produce the xml?
Here below the sample of my data:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<PartnersProfile xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">
<ID>10</ID>
<NAME>Table 10</NAME>
<Record>
<PARTNER_ID>1</PARTNER_ID>
<DESCRIPTION>customer</DESCRIPTION>
<subscription>2004</subscription>
<club_LIST>1</club_LIST>
<club_LIST>4</club_LIST>
<club_LIST>6</club_LIST>
<club_LIST>9</club_LIST>
</Record>
<Record>
<PARTNER_ID>1</PARTNER_ID>
<DESCRIPTION>customer</DESCRIPTION>
<subscription>2004</subscription>
<club_LIST>1</club_LIST>
<club_LIST>4</club_LIST>
<club_LIST>6</club_LIST>
<club_LIST>9</club_LIST>
</Record>
</PartnersProfile>
Consider transforming the XML to an itemized version by each club_LIST with repeating values for ancestor elements. You can run the below XSLT 1.0 by many tools and programming languages including Perl (from your profile) or Excel VBA.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/PartnersProfile">
<xsl:copy>
<xsl:apply-templates select="descendant::club_LIST"/>
</xsl:copy>
</xsl:template>
<xsl:template match="club_LIST">
<Record>
<xsl:copy-of select="ancestor::PartnersProfile/*[name()!='Record']"/>
<xsl:copy-of select="ancestor::Record/*[name()!='club_LIST']"/>
<club_LIST><xsl:apply-templates select="node()"/></club_LIST>
</Record>
</xsl:template>
</xsl:stylesheet>
Online Demo

hello world xml -> json template

I'm trying to transform an xml input to a json output. My XSLT 1.0 is pretty proficient my XSLT 2.0/3.0 not so.
I thought I'd start with a hello world style template and build from there.
My belief is that you can simply create an output as map/array data structure and then some magic will map that into the desired output, so this is my first attempt (I've not defined an input, because any old xml will do in this example, it ignores it):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="3.0">
<xsl:output method="json" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="foo">
<map xmlns="http://www.w3.org/2005/xpath-functions">
<string key='desc'>Distances between several cities, in kilometers.</string>
<string key='updated'>2014-02-04T18:50:45</string>
<boolean key="uptodate">true</boolean>
<null key="author"/>
<map key='cities'>
<array key="Brussels">
<map>
<string key="to">London</string>
<number key="distance">322</number>
</map>
<map>
<string key="to">Paris</string>
<number key="distance">265</number>
</map>
<map>
<string key="to">Amsterdam</string>
<number key="distance">173</number>
</map>
</array>
</map>
</map>
</xsl:variable>
<xsl:value-of select="xml-to-json($foo)"/>
</xsl:template>
</xsl:stylesheet>
this almost works but I get a string output...(the '"' chars exist in the output file includeing all the escaping, so not a valid json output).
"{\"desc\":\"Distances between several cities, in kilometers.\",\"updated\":\"2014-02-04T18:50:45\",\"uptodate\":true,\"author\":null,\"cities\":{\"Brussels\":[{\"to\":\"London\",\"distance\":322},{\"to\":\"Paris\",\"distance\":265},{\"to\":\"Amsterdam\",\"distance\":173}]}}"
If there are any basic guides to do this, then please let me know, the web is awash with odd examples, out of date instruction based on XSLT 1.0/2.0 or hard to understand pdfs discussing more in depth scenarios.
The function you use already gives you a string with the JSON (see https://www.w3.org/TR/xpath-functions-31/#func-xml-to-json) so if you want to write that to a file just use <xsl:output method="text"/>.
The json output method mainly makes sense if you construct XDM/XPath 3.1 maps/arrays and want to serialize them as JSON.
For your sample I would also use <xsl:template name="xsl:initial-template"> instead of <xsl:template match="/">, then you don't need to provide any dummy input XML at all but can just start with that default named template using e.g. -it from the command line or callTemplate(null, ..) from the API.

Azure Logic App ignores indent="yes" when transforming XML

I'm using Azure Logic App to transform a CSV file to XML, everything was initially set up in BizTalk first to generate the relevant XSDs and XSL which worked perfectly fine. But when I use Azure Logic App the output XML file is all in one line even though I made sure it has indent="yes" in the XSL file.
I know I can use notepad++ to pretty print the result and save the file, but surely there's a way to automatically do that in Logic App?
For those interested, I've found a setting within the Logic App, simply select Apply XSLT output attributes and that's it, no validation needed either!
I manage to get indentation when using XSLT 3.0 with e.g. the stylesheet/map doing
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:output method="xml" indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="/" name="xsl:initial-template">
<xsl:next-match/>
<xsl:comment xmlns:saxon="http://saxon.sf.net/">Run with {system-property('xsl:product-name')} {system-property('xsl:product-version')} {system-property('Q{http://saxon.sf.net/}platform')}</xsl:comment>
</xsl:template>
</xsl:stylesheet>
then a request of e.g.
<root><item>a</item><item>b</item></root>
is transformed to the output
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>a</item>
<item>b</item>
</root>
<!--Run with SAXON HE 9.8.0.8 -->
I don't know how they run the XSLT 1.0 processor to ignore the xsl:output settings, seems a flaw or quirk in the pipeline.

"Reserved namespace" error occurs when chaining named templates with "xsl:original" in XSLT-3.0

I'm trying to chain named templates in XSLT 3.0 using the "xsl:original" feature, but I get a reserved-name namespace error.
As an example, I use a named template add-atts that is defined in two included stylesheets:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs" version="3.0">
<xsl:template match="/">
<root>
<xsl:apply-templates select="root/line"/>
</root>
</xsl:template>
<xsl:template match="line">
<xsl:copy>
<xsl:call-template name="add-atts"/> <!-- USED HERE -->
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:import href="add-foo.xsl"/> <!-- DEFINED HERE -->
<xsl:import href="add-bar.xsl"/> <!-- DEFINED HERE -->
</xsl:stylesheet>
The first included stylesheet has a named template that adds a #foo attribute:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs" version="3.0">
<xsl:template name="add-atts">
<xsl:attribute name="att1">foo</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
The second included stylesheet has a named template of the same name (which takes precedence due to ordering) that adds a #bar attribute, then attempts to call the overridden template from the previous file:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs" version="3.0">
<xsl:template name="add-atts">
<xsl:attribute name="att2">bar</xsl:attribute>
<xsl:call-template name="xsl:original"/> <!-- HERE -->
</xsl:template>
</xsl:stylesheet>
When I run this on the following input file
<root>
<line>1</line>
<line>2</line>
<line>3</line>
</root>
I get the following error:
$ java -jar .../Saxon-HE-9.9.1-4.jar in.xml trans.xsl
Static error in xsl:call-template/#name on line 8 column 46 of add-bar.xsl:
XTSE0080: Namespace prefix xsl refers to a reserved namespace
Errors were reported during stylesheet compilation
The xsl: namespace is declared, the XSLT version is set to 3.0, and the usage is the same as what's shown in this example from the deprecated XSL-LIST mailing list. What am I missing?
(The actual intent is to chain named templates when creating plugins for the DITA Open Toolkit.)
Thanks in advance!
The functionality exists in the context of the new XSLT 3 feature of packages, see https://www.w3.org/TR/xslt-30/#refer-to-overridden. Neither the spec nor that thread you have linked to seem to introduce this functionality in the context of simply xsl:imports.
To give you an example on how this can be used in XSLT 3 with packages, suppose you have a first package
<?xml version="1.0" encoding="UTF-8"?>
<xsl:package
name="http://example.com/packages/ex1"
package-version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:template name="add-atts" visibility="public">
<xsl:attribute name="att1">foo</xsl:attribute>
</xsl:template>
</xsl:package>
then you can write a second package overriding that named template and making use of <xsl:call-template name="xsl:original"/>:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:package
name="http://example.com/packages/ex2"
package-version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:use-package name="http://example.com/packages/ex1">
<xsl:override>
<xsl:template name="add-atts" visibility="public">
<xsl:attribute name="att2">bar</xsl:attribute>
<xsl:call-template name="xsl:original"/>
</xsl:template>
</xsl:override>
</xsl:use-package>
</xsl:package>
Finally you can use the second package:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs" version="3.0">
<xsl:use-package name="http://example.com/packages/ex2"></xsl:use-package>
<xsl:output indent="yes"/>
<xsl:template match="/">
<root>
<xsl:apply-templates select="root/line"/>
</root>
</xsl:template>
<xsl:template match="line">
<xsl:copy>
<xsl:call-template name="add-atts"/> <!-- USED HERE -->
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
With Saxon from the command line, you would need to make sure you give the list of file names of the two packages with the -lib option e.g. -lib:package1.xsl;package2.xsl on Windows and -lib:package1.xsl:package2.xsl on Linux, when you run the main stylesheet.

How to replace text defined in a given tag or element using xslt, xslt string replace

Please help me with this xslt transformation.
Source Xml
<xml>
<test>This is a <bold>sample</bold> description. Please help me with a sample</text>
</xml>
Expected Output: This is a sample description. Please help me with a sample
I just need to make bold only the specified text by the xml markup.
Thank you
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="text">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="bold">
<b><xsl:apply-templates/></b>
</xsl:template>
</xsl:stylesheet>
when applied against the provided XML document:
<xml>
<text>This is a <bold>sample</bold> description. Please help me with a sample</text>
</xml>
produces the desired result in HTML:
<p>This is a <b>sample</b> description. Please help me with a sample</p>

Resources