The XML output i am getting is not in the format that i require so tried some code to change the format but was unable to
This is the output that i am getting
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Header>
<MessageId>{A124-B421-C325-D467}</MessageId>
<Action>find</Action>
</Header>
<Body>
<MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Run xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/Run">
<RunObject class="entity">
<A1>NA</A1>
<A2>False</A2>
<A3>02</A3>
<A4>ER</A4>
</RunObject>
<RunObject class="entity">
<A1>NA</A1>
<A2>False</A2>
<A3>03</A3>
<A4>ER</A4>
</RunObject>
</Run>
</MessageParts>
</Body>
</Envelope>
This is the XML output that i require
<?xml version="1.0" encoding="UTF-8"?>
<Document>
<Item>
<A3>NA</A3>
<A4>False</A4>
<A2>02</A2>
<A1>ER</A1>
</Item>
<Item>
<A3>NA</A3>
<A4>False</A4>
<A2>03</A2>
<A1>ER</A1>
</Item>
</Document>
This is the code that i have used to change the format of the xml that i was getting
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"
xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/Run"
exclude-result-prefixes="m r">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- move all elements to no namespace -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="m:Envelope"/>
<xsl:template match="m:Header"/>
<xsl:template match="m:MessageId"/>
<xsl:template match="m:Action"/>
<xsl:template match="m:Body"/>
<!-- rename MessageParts to Document + skip the Run wrapper -->
<xsl:template match="m:MessageParts">
<Document>
<xsl:apply-templates select="r:Run/*"/>
</Document>
</xsl:template>
<!-- rename RunObject to Item + reorder child nodes -->
<xsl:template match="r:RunObject[#class='entity']">
<Item>
<xsl:apply-templates select="r:A3" />
<xsl:apply-templates select="r:A4" />
<xsl:apply-templates select="r:A2" />
<xsl:apply-templates select="r:A1" />
</Item>
</xsl:template>
</xsl:stylesheet>
I tried the above code but was not able to change the format of the xml
Instead of:
<xsl:template match="m:Envelope"/>
that removes the Envelope node and all its descendants, you need to remove only the Envelope wrapper and continue processing its contents:
<xsl:template match="m:Envelope">
<xsl:apply-templates/>
</xsl:template>
Likewise for the other wrappers. In fact, you could replace all of these:
<xsl:template match="m:Envelope"/>
<xsl:template match="m:Header"/>
<xsl:template match="m:MessageId"/>
<xsl:template match="m:Action"/>
<xsl:template match="m:Body"/>
with:
<xsl:template match="m:*">
<xsl:apply-templates select="*"/>
</xsl:template>
Related
I need to replace the child node with another node without affecting its sub nodes, I tried matching the child node but was unable to
This is the xml format
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Header>
<MessageId>{A124-B421-C325-D467}</MessageId>
<Action>find</Action>
</Header>
<Body>
<MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Run xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/Run">
<RunObject class="entity">
<A1>NA</A1>
<A2>False</A2>
<Object class="entity">
<A3>02</A3>
</Object>
<A4>ER</A4>
</RunObject>
</Run>
</MessageParts>
</Body>
</Envelope>
This is the xml format that i require
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Header>
<MessageId>{A124-B421-C325-D467}</MessageId>
<Action>find</Action>
</Header>
<Body>
<Document>
<Item>
<A1>NA</A1>
<A2>False</A2>
<Base>
<A3>02</A3>
</Base>
<A4>ER</A4>
</Item>
</Document>
</Body>
</Envelope>
This is the code that i through which i tried to change the format
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"
xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/Run"
exclude-result-prefixes="m r">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- move all elements to no namespace -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!-- rename MessageParts to Document + skip the Run wrapper -->
<xsl:template match="m:MessageParts">
<Document>
<xsl:apply-templates select="r:Run/*"/>
</Document>
</xsl:template>
<!-- rename RunObject to Item + reorder child nodes -->
<xsl:template match="r:RunObject[#class='entity']">
<Item>
<xsl:apply-templates select="r:A1" />
<xsl:apply-templates select="r:A2" />
<xsl:template match="r:Object[#class='entity']>
<Base>
<xsl:apply-templates select="r:A3" />
</Base>
</xsl:Template>
<xsl:apply-templates select="r:A4" />
</Item>
</xsl:template>
</xsl:stylesheet>
I tried matching the Object element but was unable to since i am already matching its parent element that is RunObject
Your mistake is that you cannot define a template inside of a template. So move the <xsl:template match="r:Object[#class='entity']> to the root level and add an <xsl:apply-templates select="r:Object" /> at its place.
The stylesheet could look like this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message" xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/Run" exclude-result-prefixes="m r">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- move all elements to no namespace -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!-- rename MessageParts to Document + skip the Run wrapper -->
<xsl:template match="m:MessageParts">
<Document>
<xsl:apply-templates select="r:Run/*"/>
</Document>
</xsl:template>
<!-- rename RunObject to Item + reorder child nodes -->
<xsl:template match="r:RunObject[#class='entity']">
<Item>
<xsl:apply-templates select="r:A1" />
<xsl:apply-templates select="r:A2" />
<xsl:apply-templates select="r:Object" />
<xsl:apply-templates select="r:A4" />
</Item>
</xsl:template>
<xsl:template match="r:Object[#class='entity']">
<Base>
<xsl:apply-templates select="r:A3" />
</Base>
</xsl:template>
</xsl:stylesheet>
Its output is (nearly) as desired:
<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
<Header>
<MessageId>{A124-B421-C325-D467}</MessageId>
<Action>find</Action>
</Header>
<Body>
<Document>
<Item>
<A1>NA</A1>
<A2>False</A2>
<Base>
<A3>02</A3>
</Base>
<A4>ER</A4>
</Item>
</Document>
</Body>
</Envelope>
I added the adjective "nearly", because this result has no namespace, while the sample of your desired outcome is in the namespace
xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"
But because you defined a template that removes the namespaces of all elements, I did ignore that. I simply assume that this part of your question is erroneous.
If you like to change that, restrict the first template and add a general identity template:
<!-- move all elements to no namespace -->
<xsl:template match="*[namespace-uri() != 'http://schemas.microsoft.com/dynamics/2011/01/documents/Message']">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
This would make your output containing the root namespace:
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Header>
<MessageId>{A124-B421-C325-D467}</MessageId>
<Action>find</Action>
</Header>
<Body>
<Document xmlns="">
<Item>
<A1>NA</A1>
<A2>False</A2>
<Base>
<A3>02</A3>
</Base>
<A4>ER</A4>
</Item>
</Document>
</Body>
</Envelope>
How to rename the parent node and rearrange the child nodes simultaneously.
I tried some code but was unable to get the desired output.
This was the output that i was getting
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Header> </Header>
<Body>
<MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Run xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/Run">
<RunObject class="entity">
<A1>NA</A1>
<A2>False</A2>
<A3>02</A3>
<A4>ER</A4>
</RunObject>
<RunObject class="entity">
<A1>NA</A1>
<A2>False</A2>
<A3>03</A3>
<A4>ER</A4>
</RunObject>
</Run>
</MessageParts>
</Body>
</Envelope>
I wanted to remove the namespaces, rename the Parent tags and rearrange the child tags.
So i used this code
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"
xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/Run"
exclude-result-prefixes="m r">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- move all elements to no namespace -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!-- rename MessageParts to Document + skip the Run wrapper -->
<xsl:template match="m:MessageParts">
<Document>
<xsl:apply-templates select="r:Run/*"/>
</Document>
</xsl:template>
<xsl:template match="r:RunObject[#class='entity']">
<xsl:copy>
<xsl:apply-templates select="A3" />
<xsl:apply-templates select="A4" />
<xsl:apply-templates select="A2" />
<xsl:apply-templates select="A1" />
</xsl:copy>
</xsl:template>
<!-- rename RunObject to Item -->
<xsl:template match="r:RunObject[#class='entity']">
<Item>
<xsl:apply-templates />
</Item>
</xsl:template>
</xsl:stylesheet>
I was able to remove the namespaces, rename the parent tags but was unable to rearrange the child tags. The output i got was this
?xml version="1.0" encoding="UTF-8"?>
<Envelope>
<Header> </Header>
<Body>
<Document>
<Item>
<A1>NA</A1>
<A2>False</A2>
<A3>02</A3>
<A4>ER</A4>
</Item>
<Item>
<A1>NA</A1>
<A2>False</A2>
<A3>03</A3>
<A4>ER</A4>
</Item>
</Document>
</Body>
</Envelope>
But the desired output is this
<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
<Header> </Header>
<Body>
<Document>
<Item>
<A3>02</A3>
<A4>ER</A4>
<A2>False</A2>
<A1>NA</A1>
</Item>
<Item>
<A3>03</A3>
<A4>ER</A4>
<A2>False</A2>
<A1>NA</A1>
</Item>
</Document>
</Body>
</Envelope>
Problem #1:
You have two templates matching the same nodes:
<xsl:template match="r:RunObject[#class='entity']">
Only the last one of these will be applied.
Problem #2:
The elements A1, A2, A3 and A4 are in a namespace inherited from their Run ancestor. You need to use the prefix bound to that namespace when selecting them.
See if this works for you:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"
xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/Run"
exclude-result-prefixes="m r">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- move all elements to no namespace -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!-- rename MessageParts to Document + skip the Run wrapper -->
<xsl:template match="m:MessageParts">
<Document>
<xsl:apply-templates select="r:Run/*"/>
</Document>
</xsl:template>
<!-- rename RunObject to Item + reorder child nodes -->
<xsl:template match="r:RunObject[#class='entity']">
<Item>
<xsl:apply-templates select="r:A3" />
<xsl:apply-templates select="r:A4" />
<xsl:apply-templates select="r:A2" />
<xsl:apply-templates select="r:A1" />
</Item>
</xsl:template>
</xsl:stylesheet>
How to change the output of the xml.
This is the output that i am getting.
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Header> </Header>
<Body>
<MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Run xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/Run">
<RunObject class="entity">
<A1>NA</A1>
<A2>False</A2>
<A3>02</A3>
<A4>ER</A4>
</RunObject>
<RunObject class="entity">
<A1>NA</A1>
<A2>False</A2>
<A3>03</A3>
<A4>ER</A4>
</RunObject>
</Run>
</MessageParts>
</Body>
</Envelope>
And the output that i want is this
<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
<Header> </Header>
<Body>
<Document>
<Item>
<A1>NA</A1>
<A2>False</A2>
<A3>02</A3>
<A4>ER</A4>
</Item>
<Item>
<A1>NA</A1>
<A2>False</A2>
<A3>03</A3>
<A4>ER</A4>
</Item>
</Document>
</Body>
</Envelope>
I have tried various things but still i am not to make one final change.
I am not able to change <Runobject class="Entity"> to <Item>.
This the xslt code that i used to alter the xml format
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:s="http://schemas.microsoft.com/dynamics/2008/01/documents/Run"
>
<xsl:output method="xml" indent="yes"/>
**Removes the run tag along with the namespace
<xsl:template match="s:Run">
<xsl:apply-templates select="*"/>
</xsl:template>
**Copies all the tags
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
**Used this code to replace the <RunObject class="entity"> with <Item> but is not working
<xsl:template match="RunObject[#class='Entity']">
<xsl:element name="Item">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
**Removes all namespaces
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
**Copies 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>
I am fairly new to xslt so i mght have certain mistakes while writing the code
There are two reasons why your template:
<xsl:template match="RunObject[#class='Entity']">
<xsl:element name="Item">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
does not match anything:
RunObject is in a namespace, and you are not using a prefix;
XML is case-sensitive; the class attribute contains "entity", not "Entity".
It should work if you do:
<xsl:template match="s:RunObject[#class='entity']">
<xsl:element name="Item">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
Other than that, I believe you could shorten the entire thing considerably - say:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"
xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/Run"
exclude-result-prefixes="m r">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- move all elements to no namespace -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!-- rename MessageParts to Document + skip the Run wrapper -->
<xsl:template match="m:MessageParts">
<Document>
<xsl:apply-templates select="r:Run/*"/>
</Document>
</xsl:template>
<!-- rename RunObject to Item -->
<xsl:template match="r:RunObject[#class='entity']">
<Item>
<xsl:apply-templates />
</Item>
</xsl:template>
</xsl:stylesheet>
I am using xslt to convert xml to xml.
<root>
<elem>
<confs>
<conf1>1</conf1>
<conf2>2</conf2>
</confs>
</elem>
</root>
My XSL
<xsl:template match="elem">
<xsl:copy>
<xsl:attribute name="className">confs</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="confs">
<confs>
<xsl:for-each select="*">
<conf>
<value>
<xsl:value-of select="node()"></xsl:value-of>
</value>
</conf>
</confs>
</xsl:template>
desired output:
<root>
<elem className="confs>
<confs>
<conf>
<value>1</value>
</conf>
<conf>
<value>1</value>
</conf>
</confs>
</elem>
</root>
When ran each template individaully they are good. But I run both the confs template is not affected at all.
Any help?
I believe the most straightforward way to achieve your output would be by:
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="elem">
<elem className="confs">
<xsl:apply-templates/>
</elem>
</xsl:template>
<xsl:template match="confs/*">
<conf>
<value>
<xsl:value-of select="."/>
</value>
</conf>
</xsl:template>
</xsl:stylesheet>
i am beginner in XSLT and i am using it to transform XML to XML
This is the source XML i receive
Source XML:
<Response>
<Pax>
<Id>1</Id>
</Pax>
<Pax>
<Id>2</Id>
</Pax>
<Travelers>
<Traveler>
<Name>ABC</Name>
</Traveler>
<Traveler>
<Name>XYZ</Name>
</Traveler>
</Travelers>
</Response>
I have written below XSLT
XSLT:
<?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="Response">
<xsl:element name="Root">
<xsl:apply-templates select="Travelers/Traveler"/>
</xsl:element>
</xsl:template>
<xsl:template match="Traveler">
<xsl:element name="Person">
<xsl:element name="PId">
<xsl:value-of select="//Pax/Id[position()]" />
</xsl:element>
<xsl:element name="Name">
<xsl:value-of select="Name" />
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Output:
<Root>
<Person>
<PId>1</PId>
<Name>ABC</Name>
</Person>
<Person>
<PId>1</PId>
<Name>XYZ</Name>
</Person>
</Root>
I would like to generate below XML output
Expected Output:
<Root>
<Person>
<PId>1</PId>
<Name>ABC</Name>
</Person>
<Person>
<PId>2</PId>
<Name>XYZ</Name>
</Person>
</Root>
As shown in above XML the only issue is with PId, it should have value 2.
Please help. Thanks.
Here's a relatively simple solution.
When this XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="/*">
<Root>
<xsl:apply-templates select="Pax" />
</Root>
</xsl:template>
<xsl:template match="Pax">
<xsl:variable name="vPosition" select="position()" />
<Person>
<PId>
<xsl:value-of select="Id" />
</PId>
<Name>
<xsl:value-of select="/*/Travelers/*[$vPosition]/Name" />
</Name>
</Person>
</xsl:template>
</xsl:stylesheet>
...is applied to the original XML:
<Response>
<Pax>
<Id>1</Id>
</Pax>
<Pax>
<Id>2</Id>
</Pax>
<Travelers>
<Traveler>
<Name>ABC</Name>
</Traveler>
<Traveler>
<Name>XYZ</Name>
</Traveler>
</Travelers>
</Response>
...the wanted result is produced:
<Root>
<Person>
<PId>1</PId>
<Name>ABC</Name>
</Person>
<Person>
<PId>2</PId>
<Name>XYZ</Name>
</Person>
</Root>
<?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="Response">
<Root>
<xsl:for-each select="Travelers/Traveler">
<Person>
<xsl:variable name="index" select="position()" />
<Pid><xsl:value-of select="//Pax[$index]/Id"/></Pid>
<Name><xsl:value-of select="Name"/></Name>
</Person>
</xsl:for-each>
</Root>
</xsl:template>
</xsl:stylesheet>
<?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"/>
<xsl:template match="/Response">
<Root>
<xsl:for-each select="Pax">
<xsl:variable name="pos" select="position()"/>
<Person>
<PId>
<xsl:value-of select="Id"/>
</PId>
<xsl:apply-templates select="//Travelers">
<xsl:with-param name="pos" select="$pos"/>
</xsl:apply-templates>
</Person>
</xsl:for-each>
</Root>
</xsl:template>
<xsl:template match="Travelers">
<xsl:param name="pos"/>
<xsl:for-each select="//Name">
<xsl:if test="position()=$pos">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>