I need to copy all nodes and then change one element according to the following conditions.
If all nodes ship are 0, then replace = Rejected
If all node qty are ship, then replace = Accepted
If otherwise, then replace = Changed
No error occurs with 0 values, but if the second option does not work.
Input XML
<?xml version="1.0" encoding="utf-8"?>
<root>
<a>123</a>
<b>231</b>
<c>
<xxx>
<qty>5</qty>
<ship>5</ship>
</xxx>
<xxx>
<qty>8</qty>
<ship>8</ship>
</xxx>
<xxx>
<qty>13</qty>
<ship>13</ship>
</xxx>
<xxx>
<qty>10</qty>
<ship>10</ship>
</xxx>
</c>
</root>
My XSLT
<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:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/root/a">
<a>
<xsl:choose>
<xsl:when test="not(/root/c/xxx/ship != '0')">Rejected</xsl:when>
<xsl:when test="not(/root/c/xxx/ship != /root/c/xxx/qty)">Accepted</xsl:when>
<xsl:otherwise>Changed</xsl:otherwise>
</xsl:choose>
</a>
</xsl:template>
</xsl:stylesheet>
UPD.
I begged xml, because I didn't think that the result would be through predicates
Now the structure of the input file is like this and I already use predicates
<?xml version="1.0" encoding="utf-8"?>
<root>
<a>123</a>
<b>231</b>
<c>
<xxx>
<yyy>
<what>1</what>
<qty>5</qty>
</yyy>
<yyy>
<what>2</what>
<qty>5</qty>
</yyy>
</xxx>
<xxx>
<yyy>
<what>1</what>
<qty>24</qty>
</yyy>
<yyy>
<what>2</what>
<qty>24</qty>
</yyy>
</xxx>
...
</c>
</root>
I suppose you want <xsl:when test="not(/root/c/xxx[ship != qty])">Accepted</xsl:when>.
Related
Unfortunately, i'm a newbie to XLST. I couldn't find a matching solution for my problem. I have to transform a file with XSLT 1.0. Given file:
<?xml version="1.0" encoding="UTF-8"?>
<A:A xsi:schemaLocation="urn:A A.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:A="urn:A">
<A:B>
<C xmlns="urn:C">
<D>foo</D>
</C>
</A:B>
<A:B>
<C xmlns="urn:C">
<D>bar</D>
</C>
</A:B>
</A:A>
Wanted result:
<?xml version="1.0" encoding="UTF-8"?>
<C xmlns="urn:C">
<D>foo</D>
</C>
<C xmlns="urn:C">
<D>bar</D>
</C>
I am stuck to get the desired result. My transformer:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:A="urn:A">
<xsl:output method="xml" version="1.0" encoding="UTF-8"/>
<xsl:template match="A:B">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:copy-of select="node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
produces
<?xml version="1.0" encoding="UTF-8"?>
<A:B xmlns:A="urn:A">
<C xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:C">
<D>foo</D>
</C>
</A:B>
<A:B xmlns:A="urn:A">
<C xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:C">
<D>bar</D>
</C>
</A:B>
Any ideas how to get rid of the A:B envelope?
The code at https://xsltfiddle.liberty-development.net/nbiE19Q does
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="*/*/node()"/>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
and that way processes only the grandgrandchildren and their descendants with a template that strips all namespaces but the one each element is in.
I have trouble in transform part of a xml to a new xml without namespace.
Input xml is:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<node1 xmlns="http://a.com">
<ServiceData>
<b:test xmlns:b="http://b.com">
<b:somtag>
</b:somtag>
</b:test>
</ServiceData>
</node1>
and what I want is:
<a>
<c>
<ServiceData>
<b:test xmlns:b="http://b.com">
<b:somtag>
</b:somtag>
</b:test>
</ServiceData>
</c>
</a>
The format I want is with no namespace for ServiceData.
Any help is appreciated, thanks.
Added, I tried to use this xsl, but I can't remove "xmlns="http://a.com""
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:test="http://a.com" exclude-result-prefixes="test">
<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes" />
<xsl:template match="/">
<a><c><ServiceData><xsl:copy-of select="//test:ServiceData/*"/></ServiceData></c></a>
</xsl:template>
</xsl:stylesheet>
The result I got is:
<a>
<c>
<ServiceData>
<b:test xmlns:b="http://b.com" xmlns="http://a.com">
<b:somtag>
</b:somtag>
</b:test>
</ServiceData>
</c>
</a>
How about:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://a.com">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="/node1">
<a>
<c>
<ServiceData>
<xsl:copy-of select="ServiceData/*" copy-namespaces="no" />
</ServiceData>
</c>
</a>
</xsl:template>
</xsl:stylesheet>
Added:
I assumed you could use an XSLT 2.0 processor, because your stylesheet says version="2.0". If that's not true, then you cannot use xsl:copy-of; instead, you must reconstruct the elements with their original names and namespaces:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:test="http://a.com"
exclude-result-prefixes="test">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/test:node1">
<a>
<c>
<ServiceData>
<xsl:apply-templates select="test:ServiceData/*"/>
</ServiceData>
</c>
</a>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Note:
A redundant namespace declaration should not make any difference to the receiving application. The results received here are semantically identical to the result you show in your question.
I have a XML below, where new lines are added after each line at Note__c tag. I need to produce the XML by splitting them into multiple Note__c tags.
Input XML-
<?xml version="1.0" encoding="UTF-8"?>
<snotification>
<data>
<schema>yify-xjmoeLTbNXA560rHQ</schema>
<payload>
<Note__c>01/15/2020
123456
DFGRTE766
6tgBFR</Note__c>
<Line_Length__c>72.0</Line_Length__c>
<CreatedById>00554000003OENsAAO</CreatedById>
<Contact_Name__c/>
<Sent_By_Name__c>SBM</Sent_By_Name__c>
<CreatedDate>2020-01-15T16:10:40.551Z</CreatedDate>
<Order_Number__c>14831</Order_Number__c>
<Does_not_require_reformatting__c>false</Does_not_require_reformatting__c>
</payload>
<event>
<replayId>139219</replayId>
</event>
</data>
<channel>/event/Order_Note__e</channel>
</snotification>
Where Note__c contains multiple strings with new line added after each(except the last one)
Expected Output -
<?xml version="1.0" encoding="UTF-8"?>
<snotification>
<data>
<schema>yify-xjmoeLTbNXA560rHQ</schema>
<payload>
<Notes>
<Note__c>01/15/2020</Note__c>
<Note__c>123456</Note__c>
<Note__c>DFGRTE766</Note__c>
<Note__c>6tgBFR</Note__c>
</Notes>
<Line_Length__c>72.0</Line_Length__c>
<CreatedById>00554000003OENsAAO</CreatedById>
<Contact_Name__c/>
<Sent_By_Name__c>SBM</Sent_By_Name__c>
<CreatedDate>2020-01-15T16:10:40.551Z</CreatedDate>
<Order_Number__c>14831</Order_Number__c>
<Does_not_require_reformatting__c>false</Does_not_require_reformatting__c>
</payload>
<event>
<replayId>139219</replayId>
</event>
</data>
<channel>/event/Order_Note__e</channel>
</snotification>
I have written this XSLT but it is missing few tags under the payload element -
<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="snotification/data/payload">
<Notes>
<xsl:for-each select="tokenize(Note__c,'\n')">
<Note__c>
<xsl:value-of select="."/>
</Note__c>
</xsl:for-each>
</Notes>
</xsl:template>
</xsl:stylesheet>
Output of this-
<?xml version="1.0" encoding="UTF-8"?>
<snotification>
<data>
<schema>yify-xjmoeLTbNXA560rHQ</schema>
<Notes>
<Note__c>01/15/2020</Note__c>
<Note__c> 123456</Note__c>
<Note__c> DFGRTE766</Note__c>
<Note__c> 6tgBFR</Note__c>
</Notes>
<event>
<replayId>139219</replayId>
</event>
</data>
<channel>/event/Order_Note__e</channel>
</snotification>
not sure what is missing.
Thanks
Sugata
Change your XSLT to
<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="snotification/data/payload/Note__c">
<Notes>
<xsl:for-each select="tokenize(.,'\n')">
<Note__c>
<xsl:value-of select="normalize-space(.)"/>
</Note__c>
</xsl:for-each>
</Notes>
</xsl:template>
</xsl:stylesheet>
The output should be as desired.
I have got 2 source to the XSLT, which needs to be mapped to the target. Have given below the source and desired output. The first source XML is in a collection which needs to be iterated to fetch the value.
Input Payload:
XML 1:
<ParticipentsCollection>
<Participents>
<Email>PM#y.com</Email>
<Role>PM</Role>
</Participents>
<Participents>
<Email>BM#y.com</Email>
<Role>BM</Role>
</Participents>
<Participents>
<Email>CM#y.com</Email>
<Role>CM</Role>
</Participents>
</ParticipentsCollection>
XML 2:
<Project>
<ID>1</ID>
<Name>XYZ</Name>
<Status>Req Gathering</Status>
</Project>
Desired Output:
<ProjectDetails>
<ID>1</ID>
<Name>XYZ</Name>
<Status>Req Gathering</Status>
<PM>PM#y.com</PM>
<BM>PM#y.com</BM>
<CM>>CM#y.com</CM>
</ProjectDetails>
If you are using XSLT 1.0 use:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="exslt msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="Doc2"><xsl:copy><xsl:copy-of select="document('Untitled2.xml')/Project"></xsl:copy-of></xsl:copy></xsl:param>
<xsl:template match="ParticipentsCollection">
<ProjectDetails>
<xsl:copy-of select="exslt:node-set($Doc2)/Project/*"/>
<xsl:for-each select="Participents">
<xsl:element name="{Role}"><xsl:value-of select="Email"/></xsl:element>
</xsl:for-each>
</ProjectDetails>
</xsl:template>
</xsl:stylesheet>
and if 2.0 use:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="Doc2"><xsl:copy><xsl:copy-of select="document('Untitled2.xml')/Project"></xsl:copy-of></xsl:copy></xsl:param>
<xsl:template match="ParticipentsCollection">
<ProjectDetails>
<xsl:copy-of select="$Doc2/Project/*"/>
<xsl:for-each select="Participents">
<xsl:element name="{Role}"><xsl:value-of select="Email"/></xsl:element>
</xsl:for-each>
</ProjectDetails>
</xsl:template>
</xsl:stylesheet>
I am running this XSLT on XML1 and keeping XML2 in $Doc2 param to get output:
<ProjectDetails>
<ID>1</ID>
<Name>XYZ</Name>
<Status>Req Gathering</Status>
<PM>PM#y.com</PM>
<BM>BM#y.com</BM>
<CM>CM#y.com</CM>
</ProjectDetails>
I am working XSLT where the source looks like this.
Source:
<Data>
<AB>all</AB>
<AB>all2</AB>
<CD>hhhhhh</CD>
<DE>hhhshhh</DE>
</Data>
Need to write XSLT to get output as
<Info>
<XXX>
<TTT value="all"/>
<TTT value="all2"/>
</XXX>
<!-- ....-->
<!-- ..to het all the elements.. -->
</Info>
I have to write xslt to match tag.
<xsl:template match="AB">
</xsl:template>
I can do it by matching Data tag.
<?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:template match="Data">
<info>
<XXX>
<xsl:for-each select="AB">
<TTT>
<xsl:attribute name="value">
<xsl:value-of select="."/>
</xsl:attribute>
</TTT>
</xsl:for-each>
</XXX>
</info>
</xsl:template>
</xsl:stylesheet>
Can any one help me out how to do it by matching AB tag
<xsl:template match="AB">
</xsl:template>
Thank you.
I think you are asking how do you use xsl:apply-templates. If so, your XSLT would look like this
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Data">
<info>
<XXX>
<xsl:apply-templates select="AB"/>
</XXX>
</info>
</xsl:template>
<xsl:template match="AB">
<TTT value="{.}"/>
</xsl:template>
</xsl:stylesheet>
Do also note the use of Attribute Value Templates in the AB template to simplify the XSLT.
If you also require the other non-AB elements to be output unchanged, you would make use of the identity transform in your XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Data">
<info>
<XXX>
<xsl:apply-templates select="AB"/>
</XXX>
<xsl:apply-templates select="node()[not(self::AB)]" />
</info>
</xsl:template>
<xsl:template match="AB">
<TTT value="{.}"/>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This would also match all non-AB elements, outputing following the XXX element. In your case, it would output the following:
<info>
<XXX>
<TTT value="all" />
<TTT value="all2" />
</XXX>
<CD>hhhhhh</CD>
<DE>hhhshhh</DE>
</info>
Of course, there is no reason you couldn't have other templates matching elements like CD or DE to transform those too.