Adding element in middle of xml using xslt - 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>

Related

Duplicate a node and child elements if it occurs only once

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>

xslt copy child note and add extra nodes

For the following xml:
<root>
<employees>
<employee>
<Name>ABC</Name>
<Dept>CS</Dept>
<Designation>sse</Designation>
</employee>
</employees>
</root>
I use this xslt:
<?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>
I would like to achieve the following output
<employee>
<Name>ABC</Name>
<Age>34</Age>
<Dept>CS</Dept>
<Domain>Insurance</Domain>
<Designation>sse</Designation>
</employee>
I don't know what xpath shall I use to limit the result only to employee node.
Well, processing starts at the document node (root node) denoted by / thus if you write a template
<xsl:template match="/">
<xsl:apply-templates select="//employee"/>
</xsl:template>
you only process any employee descendants of the document with the rest of the templates.
See https://xsltfiddle.liberty-development.net/pPqsHT6 for a working demo of above suggestion integrated into your stylesheet, the whole code is
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output 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="Name">
<xsl:copy-of select="."/>
<Age>34</Age>
</xsl:template>
<xsl:template match="Dept">
<xsl:copy-of select="."/>
<Domain>Insurance</Domain>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="//employee"/>
</xsl:template>
</xsl:stylesheet>

XSL how to exclude some children in output?

Beginner XSL question..and I know there are similar questions and answers posted, but I can't figure out how to apply them to my XSLT...
My source XML looks like (this is just a fragment of a much larger XML file)
<?xml version="1.0" encoding="UTF-8"?>
<COLLECTION><Release NAME="Release" TYPE="Unknown" STATUS="0">
<Transaction>
<TransactionNumber>4</TransactionNumber>
<ReleaseNumber>4</ReleaseNumber>
<PrimaryObjectID>OR:wt.part.WTPart:121581:416986630-1502721046884-982634822-1-0-0-127#ODIGettingStarted.tri.co.uk</PrimaryObjectID>
<CreatedBy>orgadmin</CreatedBy>
<CreatedDate>2017-09-27 08:34:31 EDT</CreatedDate>
<Locale>en_US</Locale>
<Destination>CRP1</Destination>
</Transaction>
</Release>
I want to exclude the Locale and Destination nodes from the output.
My complete solution will be more complex that requires me to split the XML into three, hence my use of but the relevant code I have so far is :-
<?xml version = "1.0" encoding = "UTF-8"?>
<xsl:stylesheet version = "2.0"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:param name ="outputFileDir" select="'file:///D:/workspace/TPHMOT_xsl/TPHMOT_xsl/xsl_output'"/>
<xsl:template match ="/">
<xsl:result-document href="{$outputFileDir}/ESI_ItemMasters_1.xml" method="xml" indent="yes">
<COLLECTION>
<xsl:apply-templates select="COLLECTION/Release"/>
</COLLECTION>
</xsl:result-document>
<xsl:result-document href="{$outputFileDir}/ESI_ConfigurableItem_1.xml" method="xml" indent="yes">
<COLLECTION>
<xsl:apply-templates select="COLLECTION/Release"/>
</COLLECTION>
</xsl:result-document>
<xsl:result-document href="{$outputFileDir}/ESI_GenericBOM_1.xml" method="xml" indent="yes">
<COLLECTION>
<xsl:apply-templates select="COLLECTION/Release"/>
</COLLECTION>
</xsl:result-document>
</xsl:template>
<xsl:template match="Release">
<xsl:copy-of select="self::node()"/>
</xsl:template>
</xsl:stylesheet>
This outputs
<?xml version="1.0" encoding="UTF-8"?>
<COLLECTION>
<Release NAME="Release" TYPE="Unknown" STATUS="0">
<Transaction>
<TransactionNumber>4</TransactionNumber>
<ReleaseNumber>4</ReleaseNumber>
<PrimaryObjectID>OR:wt.part.WTPart:121581:416986630-1502721046884-982634822-1-0-0-127#ODIGettingStarted.tri.co.uk</PrimaryObjectID>
<CreatedBy>orgadmin</CreatedBy>
<CreatedDate>2017-09-27 08:34:31 EDT</CreatedDate>
<Locale>en_US</Locale>
<Destination>CRP1</Destination>
</Transaction>
</Release>
</COLLECTION>
How can I adapt my XSL to exclude Locale and Destination child nodes?
Many thanks in advance for any help offered!
Instead of copying your complete element in
<xsl:template match="Release">
<xsl:copy-of select="self::node()"/>
</xsl:template>
you only need to use the identity transformation
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
and then empty template(s) to prevent the elements you don't want from being copied:
<xsl:template match="Locale | Destination"/>

How can we convert XML elements into a different namespace in xslt

I have an input xml
<Request xmlns="http://hgkg.ghg.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<AppointmentInfo xmlns="">
<AppointmentId/>
<CountryCode>US</CountryCode>
<Division>A</Division>
</AppointmentInfo>
<AppointDate xmlns="">
<Day>Monday</Day>
<Date>April 2</Date>
<AppointDate>
</Request>
I need output like this
<Request xmlns="http://hgkg.ghg.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<AppointmentInfo>
<AppointmentId/>
<CountryCode>US</CountryCode>
<Division>A</Division>
</AppointmentInfo>
<AppointDate>
<Day>Monday</Day>
<Date>April 2</Date>
<AppointDate>
</Request>
i just want to remove xmlns="" in that and assume response AppointmentInfo and AppointDate are in hgkg namespace.I want to transform to it..
please help me
Building on JLRishe's earlier answer, you could try this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output 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="*/*">
<xsl:element name="{name()}" namespace="{namespace-uri(/*)}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
This would mean, each element that is not the outermost element (match="*/*") is copied to an output element with the same name, but with the namespace of the outermost element (namespace-uri(/*)).
See if that works...

XSLT: Adding a node!

How do I encapsulate nodes around my XML blocks using XSLT?
For example, I have the following XML file.
<?xml version="1.0" encoding="iso-8859-1"?>
<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" omit-xml-declaration="yes" />
<xsl:template match="/">
<Root>
<VOBaseCollection>
<xsl:apply-templates select="Root/Location" />
</VOBaseCollection>
</Root>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
My input XML file looks like this.
<Root>
<Location><Name>Pennsylvania</Name><Type>State</Type></Location>
</Root>
I wish the output to look like this.
<Root><Container>
<Location><Name>Pennsylvania</Name><Type>State</Type></Location>
</Container>
</Root>
I wish to make sure that a node called <CONTAINER> gets applied every time, it copies over information from Root/Location. What changes do I need to do to my XSLT file?
Summarizing all the answers in comments, this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="#*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Location">
<Container>
<xsl:call-template name="identity"/>
</Container>
</xsl:template>
</xsl:stylesheet>
Result:
<Root>
<Container>
<Location>
<Name>Pennsylvania</Name>
<Type>State</Type>
</Location>
</Container>
</Root>
I am just guessing, and in guess mode it seems that you want this:
EDIT: helped by another guess by Mads Hansen...
Add this to the identity template you already have:
<xsl:template match="Location">
<CONTAINER><xsl:apply-templates/></CONTAINER>
</xsl:template>