[Using xsltproc]: output of running XSLT is missing xmlns attributes - xslt

I have an XML file:
<?xml version="1.0" encoding="UTF-8"?>
<exp:Export Version="3.0"
xmlns:L7p="http://www.layer7tech.com/ws/policy"
xmlns:exp="http://www.layer7tech.com/ws/policy/export" xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<exp:References/>
<wsp:Policy xmlns:L7p="http://www.layer7tech.com/ws/policy" xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<wsp:All wsp:Usage="Required">
<L7p:AuditAssertion>
<L7p:Level stringValue="INFO"/>
</L7p:AuditAssertion>
<L7p:AuditDetailAssertion>
<L7p:Detail stringValue="2222"/>
</L7p:AuditDetailAssertion>
<L7p:AuditDetailAssertion>
<L7p:Detail stringValue="333"/>
<L7p:Level stringValue="WARNING"/>
</L7p:AuditDetailAssertion>
<wsp:OneOrMore wsp:Usage="Required">
<wsp:OneOrMore wsp:Usage="Required">
<L7p:AuditDetailAssertion>
<L7p:Detail stringValue="444"/>
<L7p:Level stringValue="FINE"/>
</L7p:AuditDetailAssertion>
</wsp:OneOrMore>
<wsp:OneOrMore wsp:Usage="Required">
<L7p:AuditDetailAssertion>
<L7p:Detail stringValue="555"/>
<L7p:Level stringValue="FINEST"/>
</L7p:AuditDetailAssertion>
</wsp:OneOrMore>
</wsp:OneOrMore>
</wsp:All>
</wsp:Policy>
</exp:Export>`
and I want to remove all of the
L7p:AuditDetailAssertion/L7p:Level
elements.
I am using the xsltproc from Redhat 7 to run the XSLT.
Here's the XSLT that I am using:
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:L7p="http://www.layer7tech.com/ws/policy"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0">
<xsl:output omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- TEMPLATE #1 -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!-- TEMPLATE #2 -->
<xsl:template match="L7p:AuditDetailAssertion/L7p:Level" />
</xsl:stylesheet>
and the output that I am getting is:
<?xml version="1.0"?>
<exp:Export xmlns:L7p="http://www.layer7tech.com/ws/policy" xmlns:exp="http://www.layer7tech.com/ws/policy/export" xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy" Version="3.0">
<exp:References/>
<wsp:Policy>
<wsp:All wsp:Usage="Required">
<L7p:AuditAssertion>
<L7p:Level stringValue="INFO"/>
</L7p:AuditAssertion>
<L7p:AuditDetailAssertion>
<L7p:Detail stringValue="2222"/>
</L7p:AuditDetailAssertion>
<L7p:AuditDetailAssertion>
<L7p:Detail stringValue="333"/>
</L7p:AuditDetailAssertion>
<wsp:OneOrMore wsp:Usage="Required">
<wsp:OneOrMore wsp:Usage="Required">
<L7p:AuditDetailAssertion>
<L7p:Detail stringValue="444"/>
</L7p:AuditDetailAssertion>
</wsp:OneOrMore>
<wsp:OneOrMore wsp:Usage="Required">
<L7p:AuditDetailAssertion>
<L7p:Detail stringValue="555"/>
</L7p:AuditDetailAssertion>
</wsp:OneOrMore>
</wsp:OneOrMore>
</wsp:All>
</wsp:Policy>
</exp:Export>
Notice that in the output, the wsp:Policy is missing the two "xmlns" attributes, "xmlns:L7p" and "xmlns:wsp".
How can I get the XSLT to include those "xmlns" attributes on the wsp:Policy element in the output XML?

Related

Extract XML Multiple Namespace with XSL

I have this XML with namespace and i need to extract on segment "NewDataSet"
I have a xsl code but it's not works
<?xml version="1.0" encoding="UTF-8"?>
<Listado_OrdenesResponse xmlns='http://tempuri.org/' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'
xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<Listado_OrdenesResult>
<diffgr:diffgram xmlns:diffgr='urn:schemas-microsoft-com:xml-diffgram-v1' xmlns:msdata='urn:schemas-microsoft-com:xml-msdata'>
<NewDataSet xmlns=''>
<RowNum diffgr:id='RowNum1' msdata:rowOrder='0'>
<MATNR>10000101</MATNR> <AUFNR>731200000047</AUFNR>
<MENGE>385</MENGE>
<MEINS>G</MEINS>
</RowNum>
<RowNum diffgr:id='RowNum2' msdata:rowOrder='1'>
<MATNR>45000528</MATNR>
<AUFNR>731200000047</AUFNR>
<MENGE>540</MENGE>
<MEINS>KG</MEINS>
</RowNum>
</NewDataSet>
</diffgr:diffgram>
</Listado_OrdenesResult>
</Listado_OrdenesResponse>
I need to extract like this segment , NewDataSet.
<NewDataSet> <RowNum>
<MATNR>10000101</MATNR>
<AUFNR>731200000047</AUFNR>
</RowNum>
<RowNum>
<MATNR>45000528</MATNR>
<AUFNR>731200000047</AUFNR>
</RowNum>
</NewDataSet>
<!-- Need To Extract -->
I have this code but the return is not as expected.
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Liquid Studio 2018 (https://www.liquid-technologies.com) -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
<xsl:template match="//NewDataSet">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
When I run the above XSL, I got this XML.
I will have the segment without namespace
<?xml version="1.0" encoding="UTF-8"?>
<RowNum xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
diffgr:id="RowNum1"
msdata:rowOrder="0">
<MATNR>10000101</MATNR>
<AUFNR>731200000047</AUFNR>
<MENGE>385</MENGE>
<MEINS>G</MEINS>
</RowNum>
<RowNum xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
diffgr:id="RowNum2"
msdata:rowOrder="1">
<MATNR>45000528</MATNR>
<AUFNR>731200000047</AUFNR>
<MENGE>540</MENGE>
<MEINS>KG</MEINS>
</RowNum>
Can you Help me?
In XSLT 2.0, use <xsl:copy-of select="XXXX" copy-namespaces='no'/>.
In XSLT 1.0 you need to use a variant of the identity template, copying elements using <xsl:element name="{local-name()}" namespace="namespace-uri()"/>.
Please don't ask XSLT questions without saying which version you are using, as many things are easier with XSLT 2.0 or 3.0!

Removing xmlns, SOAP:Envelope, SOAP:Body, from xml using XSLT

I am using XSLT to transform the xml response in my project.I have the following xml.
<?xml version="1.0" encoding="UTF-8"?>
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP:Body>
<response:performJobResponse xmlns:response="http://tempuri.org/" SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<whiteboard>
<PQ>
<SOAP:Envelope SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP:Body>
<response:performJobResponse SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<whiteboard>
<PQ>
<SOAP:Envelope SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP:Body>
<performJob loadfromcache="yes">
<jobName>PQIssueUpdate</jobName>
<whiteboard>
<PQ>
<PQContact>
<userID>Test</userID>
<password>Test#2</password>
</PQContact>
<workflowStatusComment>
<comment>Issue released. Routing Status changed from CATCHALL to Pharmancy. Issue updated by user DT76747.</comment>
</workflowStatusComment>
</PQ>
</whiteboard>
<requestNodeName>//PQ</requestNodeName>
<responseNodeName>//PQ</responseNodeName>
<jobDB>
<name>PQCustomerService</name>
<userID>sa</userID>
<password>password</password>
</jobDB>
</performJob>
</SOAP:Body>
<response>
<DST xml:lang="en-US">
<jobName version="1.0">SRVChangeLock</jobName>
<trace>0</trace>
<readable>N</readable>
<AWD>
<userID>DT76747</userID>
<password>Removed for security purposes</password>
<transaction id="2016-07-07-02.02.19.127220T01">
<createTime time="Y">2016-07-07T02:02:19:127220-05:00</createTime>
<assignedTo>DT76747</assignedTo>
<lockedBy>DT76747</lockedBy>
<customScreen>WRKXMPL</customScreen>
<workflow route="Status">
<workStep status="_NEXT" next="Y" />
</workflow>
</transaction>
</AWD>
<jobVersion>1.0</jobVersion>
<jobReturn jobName="SRV00017">
<taskName />
<description />
<value>0</value>
</jobReturn>
</DST>
</response>
</SOAP:Envelope>
</PQ>
</whiteboard>
</response:performJobResponse>
</SOAP:Body>
<response>
<DST xml:lang="en-US">
<jobName version="1.0">SRVObjectUpdate</jobName>
<trace>0</trace>
<readable>N</readable>
<AWD>
<userID>DT76747</userID>
<password>Removed for security purposes</password>
<transaction id="2016-07-07-02.02.19.127220T01" workSelected="false" hasChildWork="N" children="N" hasParent="Y" hasParentCase="Y" hasChildSource="N">
<id>2016-07-07-02.02.19.127220T01</id>
</transaction>
</AWD>
</DST>
</response>
</SOAP:Envelope>
</PQ>
</whiteboard>
<jobReturn>
<value>0</value>
</jobReturn>
</response:performJobResponse>
</SOAP:Body>
</SOAP:Envelope>
I want to remove all the xmlns content,SOAP:Envelope, <SOAP:Body> and <response>tag related content.
My final xml should be as below:
<?xml version="1.0" encoding="UTF-8"?>
<PQ>
<PQContact>
<userID>Test</userID>
<password>Test#2</password>
</PQContact>
<workflowStatusComment>
<comment>Issue released. Routing Status changed from CATCHALL to Pharmancy. Issue updated by user DT76747.</comment>
</workflowStatusComment>
</PQ>
Could you please help me out?
Please, try this transformation:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:response="http://tempuri.org/">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates select="//SOAP:Body/performJob//whiteboard/node()"/>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>

XSLT : Cummulative Sum (Conditional)

I need to do a conditional sum using XSLT. The sum of 'Oty' for each 'SKU' should be calculated only for providers listed within the 'Provider' node. In the provided example, the Qty for providerCode 4 should be skipped as its not in the 'Providers' list. I'm restricted to using XSLT 1.0.
I would appreciate any help. Thanks!
Here is the sample XML.
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Providers>
<ProviderCode>1</ProviderCode>
<ProviderCode>2</ProviderCode>
<ProviderCode>3</ProviderCode>
</Providers>
<SKU>
<SKU>XYZ</SKU>
<Description>XYZ Description</Description>
<Provider>
<ProviderCode>1</ProviderCode>
<Qty>100</Qty>
</Provider>
<Provider>
<ProviderCode>2</ProviderCode>
<Qty>67</Qty>
</Provider>
<Provider>
<ProviderCode>3</ProviderCode>
<Qty>74</Qty>
</Provider>
<Provider>
<ProviderCode>4</ProviderCode>
<Qty>62</Qty>
</Provider>
</SKU>
<SKU>
<SKU>ABC</SKU>
<Description>ABC Description</Description>
<Provider>
<ProviderCode>1</ProviderCode>
<Qty>20</Qty>
</Provider>
<Provider>
<ProviderCode>2</ProviderCode>
<Qty>77</Qty>
</Provider>
<Provider>
<ProviderCode>3</ProviderCode>
<Qty>42</Qty>
</Provider>
<Provider>
<ProviderCode>4</ProviderCode>
<Qty>631</Qty>
</Provider>
</SKU>
</Root>
Here is the required output.
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<SKU>
<SKU>XYZ</SKU>
<Qty>241</Qty>
</SKU>
<SKU>
<SKU>ABC</SKU>
<Qty>139</Qty>
</SKU>
</Root>
You can simply use sum on the nodes you want, either by comparing sum(Provider[ProviderCode = //Providers/ProviderCode]/Qty) or by using a key:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="prov" match="Providers/ProviderCode" use="."/>
<xsl:template match="Root">
<xsl:copy>
<xsl:apply-templates select="SKU"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Root/SKU">
<xsl:copy>
<xsl:copy-of select="SKU"/>
<Qty><xsl:value-of select="sum(Provider[key('prov', ProviderCode)]/Qty)"/></Qty>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Remove an XML node if an attribute of a child element matches a given value

I am a new bie in xslt and I have a requirement to remove an entire node from an xml file, if one of the child element attribute value matches a particular string.
Input xml file is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<gpm xmlns="http://www.airbus.com/topcased/gPM" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.airbus.com/topcased/gPM">
<version>1.2</version>
<version>1.2</version>
<filters>
<sheetFilter description=" " labelKey="Liste de distribution" hidden="false">
<userLogin>TO44452</userLogin>
<resultSummary>
<fieldResult name="DL_NAME"/>
<fieldResult name="DL_USERS"/>
<fieldResult name="$SHEET_STATE"/>
</resultSummary>
<scope>
<productScope name="$CURRENT_PRODUCT" includeSubProducts="false"/>
</scope>
<containers>
<sheetTypeRef name="DistributionList"/>
</containers>
</sheetFilter>
<sheetFilter .../>
....
</filters>
</gpm>
I have to remove the entire node if name attribute of element matches a particular value.
The xslt file I have used is:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1"
xmlns="http://www.airbus.com/topcased/gPM"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:gpmns="http://www.airbus.com/topcased/gPM"
exclude-result-prefixes="gpmns">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<!-- Delete extra blank lines -->
<xsl:strip-space elements="*"/>
<!-- template for any attribute node, copy -->
<xsl:template match="*|#*" name="copy_all">
<xsl:copy disable-output-escaping="yes">
<xsl:apply-templates select="#*"/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="gpmns:sheetTypeRef[#name = 'DL']">
<xsl:apply-templates match="gpmns:sheetFilter"/>
</xsl:template>
</xsl:stylesheet>
The transformation what I got is :
<?xml version="1.0" encoding="UTF-8"?>
<gpm xmlns="http://www.airbus.com/topcased/gPM" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.airbus.com/topcased/gPM">
<version>1.2</version>
<filters>
<sheetFilter description=" " labelKey="Liste de distribution" hidden="false">
<userLogin>TO44452</userLogin>
<resultSummary>
<fieldResult name="DL_NAME"/>
<fieldResult name="DL_USERS"/>
<fieldResult name="$SHEET_STATE"/>
</resultSummary>
<scope>
<productScope name="$CURRENT_PRODUCT" includeSubProducts="false"/>
</scope>
<containers/>
</sheetFilter>
<sheetFilter ..... />
Thanks in Advance..
There are at least two possibilities to manage that:
<xsl:apply-templates select="filters/sheetFilter"/>
<xsl:template match="filters/sheetFilter[containers/sheetTypeRef/#name != 'DL']">
… your output goes here …
</xsl:template>
or
<xsl:apply-templates select="filters/sheetFilter[containers/sheetTypeRef/#name != 'DL']"/>
<xsl:template match="filters/sheetFilter">
… your output goes here …
</xsl:template>
depending on your purpose.
Finally I was able to find a solution as below:
may be it'll be usefull to some one.
<xsl:template match="sheetFilter[*/sheetTypeRef[#name='DistributionList']]"/>
Thanks Rodion for your suggestion.
Susan

xpath-function max doesn't work

For unknown reason max function doesn't work.
XML input file:
test.xml
<?xml version="1.0" encoding="UTF-8"?>
<numbers>
<number>3</number>
<number>5</number>
<number>10</number>
<number>1</number>
</numbers>
XSL input file
test.xsl
<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/02/xpath-functions"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" >
<xsl:output method="xml" indent="yes" />
<xsl:template match="/numbers">
<numbers>
<xsl:value-of select="/numbers/number" />
fn:max(2, 3)
</numbers>
</xsl:template>
</xsl:stylesheet>
Output.xml
<?xml version="1.0" encoding="UTF-8"?>
<numbers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:fn="http://www.w3.org/2005/02/xpath-functions">3
fn:max(2, 3)
</numbers>
Input file is not important here, but I would like to have '3' instead of fn:max(2, 3). How to do it?
for this XSL file:
<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/02/xpath-functions"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" >
<xsl:output method="xml" indent="yes" />
<xsl:template match="/numbers">
<numbers>
<xsl:value-of select="/numbers/number" />
fn:max(2, 3)
<xsl:value-of select="max(/numbers/number)"/>
</numbers>
</xsl:template>
</xsl:stylesheet>
the following error occurs:
SystemId Unknown; Line #13; Column #49; Could not find function: max
SystemId Unknown; Line #13; Column #49; function token not found.
(Location of error unknown)java.lang.NullPointerException
(Location of error unknown)XSLT Error (javax.xml.transform.TransformerException)
: No xml-stylesheet PI found in: test.xml
Exception in thread "main" java.lang.RuntimeException: No xml-stylesheet PI foun
d in: test.xml
at org.apache.xalan.xslt.Process.doExit(Process.java:1155)
at org.apache.xalan.xslt.Process.main(Process.java:1128)
I used Xalan - Version Xalan Java 2.7.1, Command: java org.apache.xalan.xslt.Process -in test.xml -xsl test.xsl -out output.xml
There are several problems: max() needs to be in a value-of, and that you've said xsl:stylesheet version="2.0" for Xalan, which only supports XSLT 1.0. For 2.0, you'd need Saxon 9.x.
Since max() isn't part of XSLT 1.0, you need to invoke the EXSLT extension support, which Xalan does have:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:math="http://exslt.org/math">
<xsl:template match="/numbers">
<xsl:value-of select="math:max(number)"/>
</xsl:template>
</xsl:stylesheet>
or
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:math="http://exslt.org/math">
<xsl:template match="/">
<xsl:value-of select="math:max(numbers/number)"/>
</xsl:template>
</xsl:stylesheet>
You've put fn:max(2,3) in a text block. Nothing is going to interpret that. You need to put functions in value-of expressions if you want them to be evaluated.
Lavino,
Thanks for the response. I don't know why but I was pretty sure that Xalan supports 2.0... I've tested it and it works for Saxon 9.
You can use
<xsl:value-of select="max(number)" />
to get the max of all numbers.
Soln:
<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/02/xpath-functions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/numbers">
<numbers>
<max>
<xsl:value-of select="max(number)"/>
</max>
<xsl:apply-templates/>
</numbers>
</xsl:template>
<xsl:template match="number">
<number>
<xsl:value-of select="."/>
</number>
</xsl:template>
</xsl:stylesheet>
You can omit the number template and <xsl:apply-templates/> if its not reqd. This will be the output with the above xslt:
<?xml version="1.0" encoding="UTF-8"?>
<numbers xmlns:fn="http://www.w3.org/2005/02/xpath-functions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<max>10</max>
<number>3</number>
<number>5</number>
<number>10</number>
<number>1</number>
</numbers>