I need to take an XML file and create a new output file.
During creation of the output file, I need to total the quantities by material
This is my input file: -
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<data-set xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<record>
<MATERIAL>Material1</MATERIAL>
<SALES_DIST>FS</SALES_DIST>
<REGION>North</REGION>
<FIELDNM001>EA</FIELDNM001>
<MONTH>2020-01-01</MONTH>
<FIELDNM002>1</FIELDNM002>
</record>
<record>
<MATERIAL>Material1</MATERIAL>
<SALES_DIST>FS</SALES_DIST>
<REGION>North</REGION>
<FIELDNM001>EA</FIELDNM001>
<MONTH>2020-01-01</MONTH>
<FIELDNM002>1</FIELDNM002>
</record>
</data-set>
What I need to end up with is a file like this: -
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<data-set xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<record>
<MATERIAL>Material1</MATERIAL>
<SALES_DIST>FS</SALES_DIST>
<REGION>North</REGION>
<FIELDNM001>EA</FIELDNM001>
<MONTH>2020-01-01</MONTH>
<FIELDNM002>2</FIELDNM002>
</record>
</data-set>
Any ideas on what the xslt document should look like to achieve this?
Many thanks in advance.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<data-set xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<record>
<MATERIAL>Material1</MATERIAL>
<SALES_DIST>FS</SALES_DIST>
<REGION>North</REGION>
<FIELDNM001>EA</FIELDNM001>
<MONTH>2020-01-01</MONTH>
<FIELDNM002>2</FIELDNM002>
</record>
</data-set>
Starting from this reply, the following works for me using xsltproc on Linux:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:gt="http://www.gtech.com/lsp/2009-09-23"
exclude-result-prefixes="gt">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<data-set xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<record>
<MATERIAL><xsl:value-of select="//MATERIAL" /></MATERIAL>
<SALES_DIST><xsl:value-of select="//SALES_DIST" /></SALES_DIST>
<REGION><xsl:value-of select="//REGION" /></REGION>
<FIELDNM001><xsl:value-of select="//FIELDNM001" /></FIELDNM001>
<MONTH><xsl:value-of select="//MONTH" /></MONTH>
<FIELDNM002><xsl:value-of select="sum(//FIELDNM002[.])"/></FIELDNM002>
</record>
</data-set>
</xsl:template>
</xsl:stylesheet>
If other fields of the records in xml are not equals, it takes only the first records' values
Related
With my limited knowledge of XSL programming I have come up with this code:
(Post updated: XSLT is now working - Updated for the benefit of others if at all!)
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:nm="http://fsag.de/BusinessTransaction"
xmlns:env="http://www.w3.org/2001/12/soap-envelope"
exclude-result-prefixes="env">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/nm:Responses">
<xsl:copy-of select="/"/>
</xsl:template>
<xsl:template match="/Envelope">
<nm:Responses xmlns:nm="http://fsag.de/BusinessTransaction">
<BTEMessages/>
<SystemContext/>
<Error>
<xsl:copy-of select="Body"/>
</Error>
</nm:Responses>
</xsl:template>
</xsl:stylesheet>
The purpose of the is to process the file (at the end of the post) and get the result below:
Required result for 'Error' file :
<?xml version="1.0" encoding="UTF-8"?>
<nm:Response xmlns:nm="http://fsag.de/BusinessTransaction">
<BTEMessages/>
<SystemContext/>
<Error>
<Body>
<Response status="1">
<Description>DESC</Description>
<Errors>
<Error>500</Error>
</Errors>
</Response>
</Body>
</Error>
</nm:Response>
Required result for 'Response' file:
<?xml version="1.0" encoding="UTF-8"?>
<nm:Response xmlns:nm="http://fsag.de/BusinessTransaction">
<BTEMessages>
<InOrderContext xmlns:n0="http://fsag.de/BusinessTransaction">
<SendTimestamp>01-06-2017:0506230000</SendTimestamp>
</InOrderContext>
<SystemContext>
<Client>FDP</Client>
<CorrelationId>34553FTG25543SFD134</CorrelationId>
<BusinessContext>RECONCL</BusinessContext>
</SystemContext>
</BTEMessages>
</nm:Response>
*File 1: Error *
<Envelope >
<Body>
<Response status="1">
<Description>DESC</Description>
<Errors>
<Error>500</Error>
</Errors>
</Response>
</Body>
</Envelope>
File 2: Response:
<?xml version="1.0" encoding="UTF-8"?>
<nm:Response xmlns:nm="http://fsag.de/BusinessTransaction">
<BTEMessage>
<InOrderContext>
<SendTimestamp>01-06-2017:0506230000</SendTimestamp>
</InOrderContext>
<SystemContext>
<Client>FDP</Client>
<CorrelationId>34553FTG25543SFD134</CorrelationId>
<BusinessContext>RECONCL</BusinessContext>
</SystemContext>
</BTEMessage>
</nm:Response >
When i try to run the XSL is failing. Please any help here?
XSL updated with working version.
How can i check in XSLT that an XML contains XML headers?
Example XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Data>
<test>1</test>
</Data>
I want to check if the <?xml/> header exists.
<xsl:if test="xml header exists">
do something
</xsl:if>
// otherwise?
Thanks
The <?xml version="1.0" encoding="UTF-8" standalone="yes"?> is called the XML declaration and it is not part of the XSLT/XPath/XQuery data model so you can't access it or check for it using XSLT/XPath/XQuery.
I have a sample source xml like:
<?xml version="1.0" encoding="utf-16"?>
<shiporder orderid="orderid1">
<item>
item1
</item>
<item>
item2
</item>
</shiporder>
The assumptions for the transformation of my source xml is that I have a list of xPaths in this case /shiporder[1]/item[1] and /shiporder[1]/item[2] and the information that I have to transform the content of those nodes into Customer[1]/adress[1] and Customer[1]/adress[2]. In detail the result should look like:
<?xml version="1.0" encoding="utf-16"?>
<customer>
<adress>
item1
</adress>
<adress>
item2
</adress>
</customer>
Now I'm looking for a template which applies for each path in my source list ["/shiporder[1]/item"] and transform the inner text of that nodes into nodes with respect to ["Customer[1]/adress"].
First of all I thought to create templates like:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:func="http://www.functx.com">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/shiporder[1]">
<Customer>
<xsl:apply-templates select="item"/>
</Customer>
</xsl:template>
<xsl:template match="/shiporder[1]/item">
<adress>
<xsl:value-of select="text()"/>
</adress>
</xsl:template>
</xsl:stylesheet>
But later I was thinking about a function which combines the implicit call of the templates in a recursive way. I hope it is clear from here on other wise I could add some pseudo code what kind of function I have in mind.
I am working with xslt to handle the results that are returned from a web service. I first need to determine which web service the results are for. I know that the tag platformCore:record has the attribute "xsi:type="listRel:Contact or "xsi:type="listEmp:Employee". I am trying to select the value that the attribute is storing, but the colon seems to be causing some issues when I attempt to select the value.
Here is what I tried, but fails to work.
<?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" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<xsl:variable name="Type"><xsl:value-of select="//*[local-name()='searchResponse']//*[local-name()='searchResult']//*[local-name()='recordList']//*[local-name()='record']#xsi:type"/></xsl:variable>
<root>
<test><xsl:value-of select="$Type"/></test>
</root>
</xsl:template>
</xsl:stylesheet>
Here is a simple sample
<?xml version="1.0" encoding="UTF-8"?>
<searchResponse:searchResponse xmlns="urn:messages_2012_2.platform.webservices.itsthesuite.com"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:searchResponse="urn:messages_2012_2.platform.webservices.itsthesuite.com"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<platformCore:searchResult xmlns:platformCore="urn:core_2012_2.platform.webservices.itsthesuite.com">
<platformCore:status isSuccess="true"/>
<platformCore:totalRecords>1</platformCore:totalRecords>
<platformCore:recordList>
<platformCore:record internalId="154098" xsi:type="listRel:Contact" xmlns:listRel="urn:relationships_2012_2.lists.webservices.itsthesuite.com">
<listRel:entityId>John Smith</listRel:entityId>
<listRel:firstName>John</listRel:firstName>
<listRel:lastName>Smith</listRel:lastName>
<listRel:phone>(777) 777-7777</listRel:phone>
<listRel:email>john.smith#yormoms.com</listRel:email>
</platformCore:record>
</platformCore:recordList>
</platformCore:searchResult>
</searchResponse:searchResponse>
I need the solution to work for this sample as well.
Employee Sample
<?xml version="1.0" encoding="UTF-8"?>
<searchResponse xmlns="urn:messages_2012_2.platform.webservices.netsuite.com" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:searchResponse="urn:messages_2012_2.platform.webservices.netsuite.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<platformCore:searchResult xmlns:platformCore="urn:core_2012_2.platform.webservices.netsuite.com" >
<platformCore:status isSuccess="true"/>
<platformCore:totalRecords>1</platformCore:totalRecords>
<platformCore:recordList>
<platformCore:record internalId="158778" xsi:type="listEmp:Employee" xmlns:listEmp="urn:employees_2012_2.lists.webservices.netsuite.com">
<listEmp:entityId>331sfds Dipo Chaponda</listEmp:entityId>
<listEmp:salutation>Mr.</listEmp:salutation>
<listEmp:firstName>Dipo</listEmp:firstName>
<listEmp:lastName>Chaponda</listEmp:lastName>
<listEmp:email>dchapond#youmm.com</listEmp:email>
</platformCore:record>
</platformCore:recordList>
</platformCore:searchResult>
</searchResponse>
You can select an attribute using local name similarly to what you are already doing, but by prefacing the * with an #:
#*[local-name() = 'type']
However, littering your XPaths with local-name() = and double slashes is not a good practice. You should use namespaces properly, and use precise paths when they are known, although it seems that is not an option for the elements in your case because they are using different namespaces in the two examples. This should work:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="sr pc xsi"
>
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<xsl:variable name="Type">
<xsl:value-of select="*[local-name() = 'searchResponse']/
*[local-name() = 'searchResult']/
*[local-name() = 'recordList']/
*[local-name() = 'record']/
#xsi:type"/>
</xsl:variable>
<root>
<test>
<xsl:value-of select="$Type"/>
</test>
</root>
</xsl:template>
</xsl:stylesheet>
When run on your sample input, this produces the expected result:
<root>
<test>listRel:Contact</test>
</root>
I'm new to xsl and am trying to write a template to transform xml to html.
I have an xml document that begins
<?xml version="1.0" encoding="UTF-8"?>
<data xmlns:autn="http://schemas.com/aci/"
xmlns="http://iptc.org/std/nar/2006-10-01/">
<name>Bob</name>
and my xsl template begins
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:autn="http://schemas.autonomy.com/aci/">
<xsl:output method="html" omit-xml-declaration="yes"/>
<xsl:template match="/">
...
<body>
<p>user name:</p>
<p><xsl:value-of select="data/name"/></p>
The problem is, if I do
I don't get anything back for the value-of select.
If I do
I get 'Bob' but I lose all my html.
What am I missing?
You are missing the default namespace of the XML document:
xmlns="http://iptc.org/std/nar/2006-10-01/"
Add it to the XSLT as well:
<xsl:stylesheet version="1.0"
xmlns:mynamespace="http://iptc.org/std/nar/2006-10-01/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:autn="http://schemas.autonomy.com/aci/">
And use that namespace in the xsl:value-of:
<xsl:value-of select="mynamespace:data/mynamespace:name" />