Duplicate a node and child elements if it occurs only once - xslt

I need to duplicate a node and its child elements, if it occurs only once in the xml. Otherwise, the xml shouldn't be modified. For ex, in the below xml, if <dataList> occurs only once then duplicate it one more time. If not, don't change the xml at all. Only XSLT 1.0 please.
Input XML
<?xml version="1.0" encoding="UTF-8"?>
<API>
<Token/>
<root>
<dataList>
<addressOne>1</addressOne>
<addressTwo/>
<bkdn/>
</dataList>
</root>
</API>
Expected output xml
<?xml version="1.0" encoding="UTF-8"?>
<API>
<Token/>
<root>
<dataList>
<addressOne>1</addressOne>
<addressTwo/>
<bkdn/>
</dataList>
<dataList>
<addressOne>1</addressOne>
<addressTwo/>
<bkdn/>
</dataList>
</root>
</API>

As per my understanding here i want to solve 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="1.0">
<xsl:output indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root">
<xsl:copy>
<xsl:choose>
<!-- If you are looking for the dataList occurance then use count -->
<xsl:when test="count(dataList) = 1">
<!-- If you are looking for the dataList/addressOne value = 1 occurance then use below -->
<!-- <xsl:when test="dataList/addressOne=1"> -->
<xsl:apply-templates select="dataList"/>
<xsl:apply-templates select="dataList"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="dataList"/>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Related

Sending value with different tag XSLT

is there any chance can sending value to output other node response, with different path from there input request. i have input and response tag like this
Input Request:
<Root>
<Items>
<Item1>Rambutan12</Item1>
</Items>
</Root>
and i try with this code for add new node with additional info at Response
i try like this
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="text"/>
<xsl:template match="/">
<Root>
<ItemsResponse>
<xsl:call-templates select="items">
<xsl:with-param name="item1s" select="//Root/Items/Item1"/>
</xsl:call-templates>
</ItemsResponse>
</Root>
</xst:template>
<xsl:template name="items">
<xsl:param name="item1s"/>
<xsl:variable name="information">
<xsl:choose>
<xsl:when test="fn:matches($item1s, '^[a-zA-Z]*$') ">
<Item1><xsl:value-of select="$item1s"/></Item1>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<Item1><xsl:value-of select="$item1s"/></Item1>
<xsl:apply-templates select="Item1Information"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="Item1Information">
<xsl:copy>
<Item1Information>Wrong Failed Format Input</Item1Information>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Expected Result was like this
<Root>
<ItemsResponse>
<Item1>Rambutan12</Item1>
<Item1Information>Input Failed Format</ItemInformation>
</ItemsResponse>
</Root>
Any tips like for this case, thanks
It is very difficult to understand what your question is.
On the off-chance that I am guessing correctly, and that you want to add an error warning when Item1 contains any characters other than the 26 letters of the English alphabet, then you could do simply:
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="/Root">
<Root>
<ItemsResponse>
<xsl:copy-of select="Items/Item1"/>
<xsl:if test="translate(Items/Item1, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', '')">
<Item1Information>Input Failed Format</Item1Information>
</xsl:if>
</ItemsResponse>
</Root>
</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>

XSLT- Creating Parent XML element

I've fairly recently started learning XSLT after getting to grips with XML and XPath; I'm trying to complete a practice exercise; I think I'm nearly there but I've ran into a problem. So I have the following XML document:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<a>
<b></b>
<b></b>
<b></b>
<b></b>
</a>
</root>
And I'd like to surround the elements with a pair of parent elements (to output the following):
<?xml version="1.0" encoding="UTF-8"?>
<root>
<a>
<b-group>
<b></b>
<b></b>
<b></b>
<b></b>
<b-group>
</a>
Here is my XSLT:
<?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="2.0">
<xsl:template match="root">
<xsl:element name="root">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="a">
<xsl:element name="a">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="b">
<xsl:element name="b-group">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="b">
<xsl:element name="b">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Despite making several other attempts, I'm having difficulty creating the pair of elements that surround the elements; could anyone point me in the right direction of how to do this please?
You need to do this in the template matching a, for example:
<xsl:template match="a">
<a>
<b-group>
<xsl:apply-templates select="b"/>
</b-group>
</a>
</xsl:template>
Additional notes:
Use a literal result element to create an element whose name is known, instead of xsl:element.
Most of your templates do the same thing: create an element with the same name as the one being matched, and apply templates to its children. Thus they could be consolidated into one. A template like this is known as the identity transform template and it is commonly used when most of the document needs to preserved as is, with only a few modifications. This would reduce your entire stylesheet to just:
<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:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="a">
<a>
<b-group>
<xsl:apply-templates select="b"/>
</b-group>
</a>
</xsl:template>
</xsl:stylesheet>

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.

Adding element in middle of xml using xslt

Below is the actual xml:
<?xml version="1.0" encoding="utf-8"?>
<employee>
<Name>ABC</Name>
<Dept>CS</Dept>
<Designation>sse</Designation>
</employee>
And i want the output as below:
<?xml version="1.0" encoding="utf-8"?>
<employee>
<Name>ABC</Name>
<Age>34</Age>
<Dept>CS</Dept>
<Domain>Insurance</Domain>
<Designation>sse</Designation>
</employee>
Is this possible to add XML element in between using xslt?
Please give me sample!
Here is an XSLT 1.0 stylesheet that will do what you asked:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- Identity transform -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Name">
<xsl:copy-of select="."/>
<Age>34</Age>
</xsl:template>
<xsl:template match="Dept">
<xsl:copy-of select="."/>
<Domain>Insurance</Domain>
</xsl:template>
</xsl:stylesheet>
Obviously the logic will vary depending on where you will be getting the new data from, and where it needs to go. The above stylesheet merely inserts an <Age> element after every <Name> element, and a <Domain> element after every <Dept> element.
(Limitation: if your document could have <Name> or <Dept> elements within other <Name> or <Dept> elements, only the outermost ones will have this special processing. I don't think you intend for your document to have this kind of recursive structure, so it wouldn't affect you, but it's worth mentioning just in case.)
I have modified few things in the existing stylesheet ,it will allow you to choose the specific element and update in your xml.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- Identity transform -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Name[1]">
<xsl:copy-of select="."/>
<Age>34</Age>
</xsl:template>
<xsl:template match="Dept[1]">
<xsl:copy-of select="."/>
<Domain>Insurance</Domain>
</xsl:template>
</xsl:stylesheet>
XML:
<?xml version="1.0" encoding="utf-8"?>
<employee>
<Name>ABC</Name>
<Dept>CS</Dept>
<Designation>sse</Designation>
<Name>CDE</Name>
<Dept>CSE</Dept>
<Designation>sses</Designation>
</employee>