Numbering attributes of elements embedded in free text - xslt

I have the following XML, and would like to remove all ele tags, before numbering the x attribute of the ph elements that reside within some of these ele tags:
<?xml version="1.0" encoding="UTF-8"?>
<tmx version="1.4">
<body>
<tu>
<prop type="x-Context">-2050338055591740051, -2050338055591740051</prop>
<prop type="x-Origin">TM</prop>
<prop type="x-ConfirmationLevel">Translated</prop>
<tuv>
<seg>
<ele>The text </ele>
<ele>
<ph x="0" type="QIAsymphony"/>
</ele>
<ele> goes </ele>
<ele>
<ph x="0" type="470"/>
</ele>
<ele> here </ele>
<ele>
<ph x="0" type="471"/>
</ele>
<ele>.</ele>
</seg>
</tuv>
<tuv>
<seg>
<ele>El texto </ele>
<ele>
<ph x="0" type="QIAsymphony"/>
</ele>
<ele> se mete </ele>
<ele>
<ph x="0" type="471"/>
</ele>
<ele> aquí </ele>
<ele>
<ph x="0" type="470"/>
</ele>
<ele>.</ele>
</seg>
</tuv>
</tu>
</body>
</tmx>
I have the following XSLT, that performs the numbering operation, although I'm not sure what changes to make to replace the missing ele tags, once this element has been deleted from the XML:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="ph" match="tuv[1]/seg/ele/ph" use="#type" />
<xsl:strip-space elements="*" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tuv/seg/ele/ph/#x">
<xsl:attribute name="x">
<xsl:value-of select="count(key('ph', ../#type)/../preceding-sibling::ele[ph]) + 1" />
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Desired output:
<tuv>
<seg>The text
<ph x="1" type="QIAsymphony"/>
goes
<ph x="3" type="471"/>
here
<ph x="2" type="470"/>
.
</seg>
</tuv>

In the comments you say you want to remove the <ele> elements, but not their contents.
Because your XSLT is already based on the identity transform, that's easily done by adding a very simple template:
<xsl:template match="ele">
<xsl:apply-templates select="#*|node()" />
</xsl:template>
This template simply reads as: "When encountering <ele>, do not output anything but process its children". In effect <ele> is removed from the output, its children remain.
In context:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="ph" match="tuv[1]/seg/ele/ph" use="#type" />
<xsl:strip-space elements="*" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="ele">
<xsl:apply-templates select="#*|node()" />
</xsl:template>
<xsl:template match="tuv/seg/ele/ph/#x">
<xsl:attribute name="x">
<xsl:value-of select="count(key('ph', ../#type)/../preceding-sibling::ele[ph]) + 1" />
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Result:
<tmx version="1.4">
<body>
<tu>
<prop type="x-Context">-2050338055591740051, -2050338055591740051</prop>
<prop type="x-Origin">TM</prop>
<prop type="x-ConfirmationLevel">Translated</prop>
<tuv>
<seg>The text <ph x="1" type="QIAsymphony"/> goes <ph x="2" type="470"/> here <ph x="3" type="471"/>.</seg>
</tuv>
<tuv>
<seg>El texto <ph x="1" type="QIAsymphony"/> se mete <ph x="3" type="471"/> aquí <ph x="2" type="470"/>.</seg>
</tuv>
</tu>
</body>
</tmx>

Related

Best way to use for-each inside if in XSLT

I have the below XML data as input to my XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<Application>
<Data>
<Data1>
<name>Michale</name>
<age>65</age>
<Info>
<Alias name="M">
<Contactmail>abc#gmail.com</Contactmail>
<ContactPh>8988900009</ContactPh>
</Alias>
<Alias name="Q">
<Contactmail>abc#gmail.com</Contactmail>
<ContactPh>8988900009</ContactPh>
</Alias>
</Info>
</Data1>
<Data1>
<name>Albert</name>
<age>69</age>
<Info>
<Alias name="A">
<Contactmail>xyz#gmail.com</Contactmail>
<ContactPh>89889908709</ContactPh>
</Alias>
<Alias name="P">
<Contactmail>pqr#gmail.com</Contactmail>
<ContactPh>8988988779</ContactPh>
</Alias>
</Info>
</Data1>
</Data>
</Application>
And I want to pass the Data1 block whose Alias name matches with "M", i.e.:
<Application>
<Data>
<Data1>
<name>Michale</name>
<age>65</age>
<Info>
<Alias name=M>
<Contactmail>abc#gmail.com</Contactmail>
<ContactPh>8988900009</ContactPh>
</Alias>
<Alias name=Q>
<Contactmail>abc#gmail.com</Contactmail>
<ContactPh>8988900009</ContactPh>
</Alias>
</Info>
</Data1>
</Data>
</Application>
I am stuck as to how to access an loop(ie Alias) inside a test condition?
Is there any better way to do this xslt?
<xsl:for-each select="./*[local-name() = 'Application']/*[local-name() = 'Data']">
<xsl:if test="">
....
</xsl:if>
</xsl:for-each>
The following template will do the job. The explanations are in the code.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*" /> <!-- Removes unnecessary space between elements -->
<!-- identity template --> <!-- Copies all nodes not matched by other templates -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*" />
</xsl:copy>
</xsl:template>
<xsl:template match="Data1[Info/Alias/#name != 'M']" /> <!-- Ignores all Data1 elements which don't have an #name='M' attribute child -->
<xsl:template match="Data1[Info/Alias/#name = 'M']"> <!-- Matches all Data1 elements which have the desired child attribute -->
<xsl:copy>
<xsl:apply-templates select="node()|#*" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Its output is:
<?xml version="1.0"?>
<Application>
<Data>
<Data1>
<name>Michale</name>
<age>65</age>
<Info>
<Alias name="M">
<Contactmail>abc#gmail.com</Contactmail>
<ContactPh>8988900009</ContactPh>
</Alias>
<Alias name="Q">
<Contactmail>abc#gmail.com</Contactmail>
<ContactPh>8988900009</ContactPh>
</Alias>
</Info>
</Data1>
</Data>
</Application>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Application">
<xsl:copy>
<xsl:for-each select="Data/Data1">
<xsl:if test="Info/Alias[#name='M']">
<Data>
<Data1>
<xsl:apply-templates/>
</Data1>
</Data>
</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
You may also do like this

Copy & rename element using XSL

I have an XML that goes like this:
<tu>
<prop type="x-idiom-source-ipath">DOMAIN/SUBDOMAIN/FILENAME</prop>
<tuv xml:lang="IT-IT">
<seg>Prova</seg>
</tuv>
<tuv xml:lang="EN-GB">
<seg>Test</seg>
</tuv>
</tu>
I'd like to copy the prop element twice and rename it:
<tu>
<prop type="domain">DOMAIN/SUBDOMAIN/FILENAME</prop>
<prop type="subdomain">DOMAIN/SUBDOMAIN/FILENAME</prop>
<prop type="filename">DOMAIN/SUBDOMAIN/FILENAME</prop>
<tuv xml:lang="IT-IT">
<seg>Prova</seg>
</tuv>
<tuv xml:lang="EN-GB">
<seg>Test</seg>
</tuv>
</tu>
How would I do that? I don't understand how to copy and duplicate the element, I'm not competent enough.
Thank you
Well, 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:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="prop">
<prop type="domain">
<xsl:value-of select="." />
</prop>
<prop type="subdomain">
<xsl:value-of select="." />
</prop>
<prop type="filename">
<xsl:value-of select="." />
</prop>
</xsl:template>
</xsl:stylesheet>

Replace xml attribute values with constant values by xsl

there is that XML Node
<svg>
<g transform="translate(113.63-359.13)">
<use fill="#f00" xlink:href="#D"/>
<g transform="translate(72.59-8.504)">
<use xlink:href="#E"/>
<path fill="#f00" stroke="#000" stroke-linejoin="round" stroke-linecap="round" stroke-width=".24" d="m6.04 526.26h19.843v4.961h-19.843z"/>
<use xlink:href="#F"/>
</g>
<text x="20.41" y="527.6" fill="#000" font-family="Arial" font-size="8">ProcessOutbound</text>
</g>
</svg>
which can be found by this Xpath
/svg/g[text="ProcessOutbound"]/use
also this work fine
/svg/g[text="ProcessOutbound"]/use/#fill
but for some reasons that xsl is not replaceing #f00 with #00f which is what have tired
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:param name="blue" select="'#00f'"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match='/svg/g[text="ProcessOutbound"]/use'>
<xsl:attribute name='fill'>
<xsl:value-of select="'$blue'"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
actually the whole svg file is copied but the fill attribute is not replaced. I tried to achive a copy but with the replaced fill value
What is the correct way to replace attribut values with constant values by xsl ?
So the expected result should look like
<g transform="translate(113.63-359.13)">
<use fill="#00f" xlink:href="#D"/>
<g transform="translate(72.59-8.504)">
<use xlink:href="#E"/>
<path fill="#f00" stroke="#000" stroke-linejoin="round" stroke-linecap="round" stroke-width=".24" d="m6.04 526.26h19.843v4.961h-19.843z"/>
<use xlink:href="#F"/>
</g>
<text x="20.41" y="527.6" fill="#000" font-family="Arial" font-size="8">ProcessOutbound</text>
</g>
There are a few things incorrect with your XSLT:
It is trying to replace the whole 'use' element with an attribute.
You are using two pairs of quotes around $blue, which causes it to be treated as a string.
You are not using namespaces even though your XML uses a namespace.
Please try this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:svg="http://www.w3.org/2000/svg">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:param name="blue" select="'#00f'"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match='svg:g[svg:text = "ProcessOutbound"]/svg:use/#fill'>
<xsl:attribute name='fill'>
<xsl:value-of select="$blue"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
When run on your sample input, the result is:
<svg xmlns:xlink="...">
<g transform="translate(113.63-359.13)">
<use xlink:href="#D" fill="#00f" />
<g transform="translate(72.59-8.504)">
<use xlink:href="#E" xmlns:xlink="x" />
<path fill="#f00" d="m6.04 526.26h19.843v4.961h-19.843z" stroke-width=".24" stroke-linecap="round" stroke-linejoin="round" stroke="#000" />
<use xlink:href="#F" />
</g>
<text font-family="Arial" fill="#000" font-size="8" y="527.6" x="20.41">ProcessOutbound</text>
</g>
</svg>
http://www.xsltcake.com/slices/d8pdoi
If I am guessing correctly and your input is a valid SVG document, then all its elements are in the SVG namespace. IOW, your input example should actually look like this:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g transform="translate(113.63-359.13)">
<use fill="#f00" xlink:href="#D"/>
<g transform="translate(72.59-8.504)">
<use xlink:href="#E"/>
<path fill="#f00" stroke="#000" stroke-linejoin="round" stroke-linecap="round" stroke-width=".24" d="m6.04 526.26h19.843v4.961h-19.843z"/>
<use xlink:href="#F"/>
</g>
<text x="20.41" y="527.6" fill="#000" font-family="Arial" font-size="8">ProcessOutbound</text>
</g>
</svg>
And then your XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="blue" select="'#00f'"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="svg:g[svg:text='ProcessOutbound']/svg:use/#fill">
<xsl:attribute name='fill'>
<xsl:value-of select="$blue"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Assuming a well-formed input (the prefix xlink: is not bound because you did not include its namespace definition), use the stylesheet below.
Rather than matching the element use, directly match the node you'd like to modify, the fill attribute of use.
Stylesheet
Your question suggests that the second template should actually match /svg/g[8]/use/#fill if I understood correctly.
<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:strip-space elements="*"/>
<xsl:param name="blue" select="'#00f'"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/svg/g/use/#fill">
<xsl:attribute name="fill">
<xsl:value-of select="$blue"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
XML Output
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:xlink="http://www.w3.org/1999/xlink">
<g transform="translate(113.63-359.13)">
<use fill="#00f" xlink:href="#D"/>
<g transform="translate(72.59-8.504)">
<use xlink:href="#E"/>
<path fill="#f00" stroke="#000" stroke-linejoin="round" stroke-linecap="round" stroke-width=".24" d="m6.04 526.26h19.843v4.961h-19.843z"/>
<use xlink:href="#F"/>
</g>
<text x="20.41" y="527.6" fill="#000" font-family="Arial" font-size="8">ProcessOutbound</text>
</g>
</svg>
EDIT: As mentioned in a comment, try the following stylesheet if your SVG elements actually are in a namespace:
Stylesheet
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:svg="http://www.w3.org/2000/svg">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="blue" select="'#00f'"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/svg:svg/svg:g/svg:use/#fill">
<xsl:attribute name="fill">
<xsl:value-of select="$blue"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Try with this,
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:param name="blue" select="'#00f'"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/svg/g[contains(text, 'ProcessOutbound')]/use">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:attribute name='fill'>
<xsl:value-of select="$blue"/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
If this not meeting u r requirement, provide u r simple required text.

xml to xml conversion using xslt

I need to pass the XML to third party system which can be understand by third party and parse it.
Below is my input xml which I created data by fetching from database.
<FIXML>
<Header>
<RequestID>ReqID8942</RequestID>
<RequestType>DocGen</RequestType>
<Version>10.6</Version>
<BankId>01</BankId>
<ChannelId>LOS</ChannelId>
</Header>
<Body>
<Data>
**<CorpAppLimitDetailsBO>
<ApprovedLimitHomeCCY>100.0</ApprovedLimitHomeCCY>
<ApprovedLimitCCY>INR</ApprovedLimitCCY>
<ApprovedLimit>100.0</ApprovedLimit>
<LimitClassification>ROOT</LimitClassification>
</CorpAppLimitDetailsBO>
<CorpAppLimitDetailsBO>
<ApprovedLimitHomeCCY>0.0</ApprovedLimitHomeCCY>
<ApprovedLimitCCY/>
<ApprovedLimit>500.0</ApprovedLimit>
<LimitClassification>CLASSIFICATION1</LimitClassification>
</CorpAppLimitDetailsBO>
<CorpAppLimitDetailsBO>
<ApprovedLimitHomeCCY>100.0</ApprovedLimitHomeCCY>
<ApprovedLimitCCY>INR</ApprovedLimitCCY>
<ApprovedLimit>100.0</ApprovedLimit>
<LimitClassification>CLASSIFICATION1</LimitClassification>
</CorpAppLimitDetailsBO>
<CorpAppProductDetailsBO>
<ProductCategory>3</ProductCategory>
</CorpAppProductDetailsBO>
<CorpAppProductDetailsBO>
<ProductCategory>1</ProductCategory>
</CorpAppProductDetailsBO>
<CorpAppProductDetailsBO>
<ProductCategory>2</ProductCategory>
</CorpAppProductDetailsBO>**
<TemplateDetails>
<Template>tempid001</Template>
</TemplateDetails>
<SelectedClauses>
<Clauses>
<Clause>clause1</Clause>
</Clauses>
<Clauses>
<Clause>clause2</Clause>
</Clauses>
<Clauses>
<Clause>clause3</Clause>
</Clauses>
</SelectedClauses>
<Distribution>
<Email>email1#domain.com,email2#domain.com,email3#domain.com</Email>
<Print>blrkec3030,blrkec3031</Print>
</Distribution>
</Data>
</Body>
</FIXML>
I want to convert this input XML to another XML format using XSLT.
Below is the format which I need,
<FIXML>
<Header>
<RequestID>ReqID8942</RequestID>
<RequestType>DocGen</RequestType>
<Version>10.6</Version>
<BankId>01</BankId>
<ChannelId>LOS</ChannelId>
</Header>
<Body>
<Data>
**<LimitDetails>
<Limit>
<ApprovedLimitHomeCCY>100.0</ApprovedLimitHomeCCY>
<ApprovedLimitCCY>INR</ApprovedLimitCCY>
<ApprovedLimit>100.0</ApprovedLimit>
<LimitClassification>ROOT</LimitClassification>
</Limit>
<Limit>
<ApprovedLimitHomeCCY>0.0</ApprovedLimitHomeCCY>
<ApprovedLimitCCY/>
<ApprovedLimit>500.0</ApprovedLimit>
<LimitClassification>CLASSIFICATION1</LimitClassification>
</Limit>
<Limit>
<ApprovedLimitHomeCCY>100.0</ApprovedLimitHomeCCY>
<ApprovedLimitCCY>INR</ApprovedLimitCCY>
<ApprovedLimit>100.0</ApprovedLimit>
<LimitClassification>CLASSIFICATION1</LimitClassification>
</Limit>
</LimitDetails>
<ProductDetails>
<Product>
<ProductCategory>3</ProductCategory>
</Product>
<Product>
<ProductCategory>1</ProductCategory>
</Product>
<Product>
<ProductCategory>2</ProductCategory>
</Product>
</ProductDetails>**
<TemplateDetails>
<Template>tempid001</Template>
</TemplateDetails>
<SelectedClauses>
<Clauses>
<Clause>clause1</Clause>
</Clauses>
<Clauses>
<Clause>clause2</Clause>
</Clauses>
<Clauses>
<Clause>clause3</Clause>
</Clauses>
</SelectedClauses>
<Distribution>
<Email>email1#domain.com,email2#domain.com,email3#domain.com</Email>
<Print>blrkec3030,blrkec3031</Print>
</Distribution>
</Data>
</Body>
</FIXML>
Please help me out as I have to complete the task in another 2 days of time.
I tried with below code and i m getting below outputs but rest of the tags for e.g. <FIXML> , <TemplateDetails> and etc is not coming as part of output xml.
xsl code below:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes" /> <!-- This identity template copies the document -->
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*" />
</xsl:copy>
</xsl:template>
<!--
This template will only match the 'CorpAppLimitDetailsBO'
nodes and modify them the way you want.
-->
<xsl:template match="/*">
<xsl:element name="LimitDetails">
<xsl:for-each select="//CorpAppLimitDetailsBO">
<xsl:element name="Limit">
<xsl:for-each select="*">
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:element>
<xsl:element name="ProductDetails">
<xsl:for-each select="//CorpAppProductDetailsBO">
<xsl:element name="Product">
<xsl:for-each select="*">
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
output.xml below:
<?xml version="1.0" encoding="UTF-8"?>
<LimitDetails>
<Limit>
<ApprovedLimitHomeCCY>100.0</ApprovedLimitHomeCCY>
<ApprovedLimitCCY>INR</ApprovedLimitCCY>
<ApprovedLimit>100.0</ApprovedLimit>
<LimitClassification>ROOT</LimitClassification>
</Limit>
<Limit>
<ApprovedLimitHomeCCY>0.0</ApprovedLimitHomeCCY>
<ApprovedLimitCCY/>
<ApprovedLimit>500.0</ApprovedLimit>
<LimitClassification>CLASSIFICATION1</LimitClassification>
</Limit>
<Limit>
<ApprovedLimitHomeCCY>100.0</ApprovedLimitHomeCCY>
<ApprovedLimitCCY>INR</ApprovedLimitCCY>
<ApprovedLimit>100.0</ApprovedLimit>
<LimitClassification>CLASSIFICATION1</LimitClassification>
</Limit>
</LimitDetails>
<ProductDetails>
<Product>
<ProductCategory>3</ProductCategory>
</Product>
<Product>
<ProductCategory>1</ProductCategory>
</Product>
<Product>
<ProductCategory>2</ProductCategory>
</Product>
</ProductDetails>
Note: The child tag(for e.g.ApprovedLimitHomeCCY....) which i present under BO's(for e.g. CorpAppLimitDetailsBO) tag are dynamic.I shouldnt hard code in xsl.I m new to XSLT. pls help me out.
Thanks Shil and Sean for your solution. both are perfect for my requirements. but i have one more doubt now.i m adding one more child tag <DBApplicantMiscDetails> under
<CorpAppProductDetailsBO>
Input xml:
<CorpAppProductDetailsBO>
<ProductCategory>2</ProductCategory>
<DBApplicantMiscDetails>
<APPLICANTMISCID>400000</APPLICANTMISCID>
<APPLICANTID>400030</APPLICANTID>
<MISCTYPE>APPLIED</MISCTYPE>
</DBApplicantMiscDetails>
</CorpAppProductDetailsBO>
Below is the output format which i expect.
<ProductDetails>
<Product>
<ProductCategory>2</ProductCategory>
<APPLICANTMISCID>400000</APPLICANTMISCID>
<APPLICANTID>400030</APPLICANTID>
<MISCTYPE>APPLIED</MISCTYPE>
</Product>
</ProductDetails>
Thanks again.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:key name="kDetails" match="*
[starts-with(name(),'CorpApp') and
substring(name(), string-length(name()) - 8) = 'DetailsBO']"
use="substring-before(name(),'DetailsBO')" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[*[key('kDetails',substring-before(name(),'DetailsBO'))]]">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:apply-templates select="*[generate-id() =
generate-id(key('kDetails',
substring-before(name(),'DetailsBO'))[1])]" mode="group" />
<xsl:apply-templates select="*[not(
key('kDetails',substring-before(name(),'DetailsBO')))]
|comment()|processing-instruction()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="group">
<xsl:variable name="group-name" select="substring-after(substring-before(name(),'DetailsBO'),'CorpApp')" />
<xsl:element name="{$group-name}Details">
<xsl:for-each select="key('kDetails',substring-before(name(),'DetailsBO'))">
<xsl:element name="{$group-name}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
<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="/">
<xsl:apply-templates select="FIXML"/>
</xsl:template>
<xsl:template match="FIXML">
<FIXML>
<xsl:apply-templates select="Header"/>
<xsl:apply-templates select="Body"/>
</FIXML>
</xsl:template>
<xsl:template match="Header">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="Body">
<Body>
<xsl:apply-templates select="Data"/>
</Body>
</xsl:template>
<xsl:template match="Data">
<Data>
<LimitDetails>
<xsl:apply-templates select="CorpAppLimitDetailsBO"/>
</LimitDetails>
<ProductDetails>
<xsl:apply-templates select="CorpAppProductDetailsBO"/>
</ProductDetails>
<xsl:apply-templates select="TemplateDetails"/>
<xsl:apply-templates select="SelectedClauses"/>
<xsl:apply-templates select="Distribution"/>
</Data>
</xsl:template>
<xsl:template match="CorpAppLimitDetailsBO">
<Limit>
<xsl:copy-of select="child::*"/>
</Limit>
</xsl:template>
<xsl:template match="CorpAppProductDetailsBO">
<xsl:apply-templates select="ProductCategory"/>
</xsl:template>
<xsl:template match="ProductCategory">
<Product>
<xsl:copy-of select="."/>
</Product>
</xsl:template>
<xsl:template match="TemplateDetails">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="SelectedClauses">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="Distribution">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/">
<xsl:apply-templates select="FIXML"/>
</xsl:template>
<xsl:template match="FIXML">
<FIXML>
<xsl:apply-templates select="Header"/>
<xsl:apply-templates select="Body"/>
</FIXML>
</xsl:template>
<xsl:template match="Header">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="Body">
<Body>
<xsl:apply-templates select="Data"/>
</Body>
</xsl:template>
<xsl:template match="Data">
<Data>
<LimitDetails>
<xsl:apply-templates select="CorpAppLimitDetailsBO"/>
</LimitDetails>
<ProductDetails>
<xsl:apply-templates select="CorpAppProductDetailsBO"/>
</ProductDetails>
<xsl:apply-templates select="TemplateDetails"/>
<xsl:apply-templates select="SelectedClauses"/>
<xsl:apply-templates select="Distribution"/>
</Data>
</xsl:template>
<xsl:template match="CorpAppLimitDetailsBO">
<Limit>
<xsl:copy-of select="child::*"/>
</Limit>
</xsl:template>
<xsl:template match="CorpAppProductDetailsBO">
<Product>
<xsl:apply-templates select="ProductCategory"/>
<xsl:apply-templates select="DBApplicantMiscDetails"/>
</Product>
</xsl:template>
<xsl:template match="ProductCategory">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="DBApplicantMiscDetails">
<xsl:copy-of select="child::*"/>
</xsl:template>
<xsl:template match="TemplateDetails">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="SelectedClauses">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="Distribution">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>

how to transform with this source and target document?

I have the XML source file in SVG present like this:
<svg>
<g id='a001' class='pools'>
<g id='b001' class='pool' name='Proc111'>
<g id='c001' class='lane' name='User111' PoolID='b001'>
<g id='d001' class='startevent' name='startevent111' LaneID='c001'></g>
</g>
<g id='c002' class='lane' name='User222' PoolID='b001'>
<g id='d002' class='gateway' name='gateway111' LaneID='c002'></g>
</g>
</g>
<g id='b002' class='pool' name='Proc222'>
<g id='c003' class='lane' name=' customer ' PoolID=' b002'>
<g id='d003' class='endevent' name='endevent111' LaneID='c003'> </g>
</g>
</g>
</g>
<g id='a002' class='messageflows'/>
</svg>
i wanna tranform to XML target as following document:
<process id='a001' name='proc111'>
<laneset>
<lane name='User111'/>
<lane name='User222'/>
</laneset>
<startevent id='d001' name='startevent111'/>
<gateway id='d002' name='gateway111'/>
</process>
<process id='a002' name='proc222'>
<laneset>
<lane name='customer'/>
</laneset>
<endevent id='d003' name='endevent111'/>
</process>
I had tried with some transformation but it was unsuccessfull...My solution is create the main template; and inside the main template(process template), I call for the other templates which are starteventtemplate, endeventtemplate, gateway template, etc. However, in the target document, I get all childrent which are present the same for each parent elements('process').
Because the real file is bigger than this example with a lot of elements...So, I've carried out the main problem to apply for the remaining elements.
Using the following stylesheet you can generate the desired output:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<processes>
<xsl:apply-templates />
</processes>
</xsl:template>
<xsl:template match="g[#class='pool']" >
<process>
<laneset>
<xsl:apply-templates mode="laneset" />
</laneset>
<xsl:apply-templates mode="startevent" />
<xsl:apply-templates mode="gateway" />
</process>
</xsl:template>
<xsl:template match="g[#class='lane']" mode="laneset">
<lane name="{#name}"/>
</xsl:template>
<xsl:template match="g[#class='startevent']" mode="startevent">
<startevent id="{#id}" name="{#name}"/>
</xsl:template>
<xsl:template match="g[#class='gateway']" mode="gateway">
<gateway id="{#id}" name="{#name}"/>
</xsl:template>
</xsl:stylesheet>
This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="g[#class='pools']">
<processes>
<xsl:apply-templates />
</processes>
</xsl:template>
<xsl:template match="g[#class='pool']" priority="1">
<process id="{#id}" name="{#name}">
<laneset>
<xsl:apply-templates/>
</laneset>
<xsl:apply-templates select="*/*"/>
</process>
</xsl:template>
<xsl:template match="g/g">
<xsl:element name="{#class}">
<xsl:copy-of select="#id[../#class != 'lane']|#name"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Output:
<processes>
<process id="b001" name="Proc111">
<laneset>
<lane name="User111" />
<lane name="User222" />
</laneset>
<startevent id="d001" name="startevent111" />
<gateway id="d002" name="gateway111" />
</process>
<process id="b002" name="Proc222">
<laneset>
<lane name=" customer " />
</laneset>
<endevent id="d003" name="endevent111" />
</process>
</processes>
EDIT: compacting code.