XML To Text through XSLT - xslt

This is the original xml file
<?xml version="1.0" encoding="utf-8"?>
<Report xsi:schemaLocation="FPPD2_AL2.srdl http://sunserver/ReportServer?%2FSunSystems%2FExample%20Reports%2FProcess%2FFPPD2_AL2.srdl&rs%3AFormat=XML&rc%3ASchema=True" Name="FPPD2_AL2.srdl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="FPPD2_AL2.srdl">
<Detail_2_1>
<Detail_2_1_Group_Collection>
<Item RowNumber="1" transactionDate="2019-11-04" description_1="PI -Local" BankSortCode="" transactionReference="T0004" DebitCredit_Description="Credit" baseAmount_baseCreditAmount="236.32" baseAmount_baseDebitAmount="0.00" baseAmount_amount_10="-236.32" SupBankAccountName="C Voice Bank Account" TransactionAmount_TransactionCreditAmount="-413.56" TransactionAmount_Amount="-413.56" CurrencyCode_3="USD" baseAmount_amount_1="236.32" SupBankAccountNumber="01234567" SupBankSortCode="123456" DebitCredit_Code="C" ReportingAmount_ReportingCreditAmount="-413.56" ReportingAmount_ReportingDebitAmount="0.00" BankProcessDate_1="20191106" AccountCode_1="CVOI001" ProfileCode_param="BACS">
<subreport>
<Report Name="FPPD2_s1.srdl">
<Detail_2_1>
<Detail_2_1_Group_Collection>
<Item PaymentAccount="52100" BankAccountName="Own Bank Account" BankAccountNumber="0011223344" />
</Detail_2_1_Group_Collection>
</Detail_2_1>
</Report>
</subreport>
</Item>
</Detail_2_1_Group_Collection>
</Detail_2_1>
</Report>
I was trying to get the value of the PaymentAccount ("52100"). Here;s my code so far, but it does not return anything
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns2="FPPD2_AL2.srdl"
xmlns:sr1="FPPD2_s1.srdl">
<xsl:output method="text"/>
<xsl:template match="ns2:Report">
<xsl:value-of select="ns2:Detail_2_1/ns2:Detail_2_1_Group_Collection/ns2:Item/ns2:subreport/ns2:Report/ns2:Detail_2_1/ns2:Detail_2_1_Group_Collection/Item[Name='PaymentAccount']"/>
</xsl:template>
</xsl:stylesheet>
I am pretty new to XSLT so I don't know if there is anything wrong with my syntax or structure?
Thank you

Instead of:
.../Item[Name='PaymentAccount']
use:
.../ns2:Item/#PaymentAccount

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!

XSLT - multiple elements values are coming in single read

I am trying to read the number element value using below xsl.
XML:
<message channel-id="64E523E5-7A27-4343-A62A-AA8FBD24EB59">
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<insertResponse>
<sys_id>4342e2a24fb142005b0e4fe18110c7f3</sys_id>
<number>INC0010038</number>
</insertResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
</message>
XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<message>
<send-parameters>
<agent-parameter>
<name>IncidentNumber</name>
<value><xsl:value-of select="message/s:Envelope/s:Body/t:insertResponse/t:number" /></value>
</agent-parameter>
</send-parameters>
</message>
</xsl:template>
</xsl:stylesheet>
The output i am getting is as below.
<?xml version="1.0" encoding="UTF-8"?>
<message>
<send-parameters>
<agent-parameter>
<name>IncidentNumber</name>
<value>4342e2a24fb142005b0e4fe18110c7f3
INC0010038</value>
</agent-parameter>
</send-parameters>
</message>
The value element is getting value from both sys-id and number tags 4342e2a24fb142005b0e4fe18110c7f3INC0010038. I want to read only number tag from the xml. I am sure that i am missing something very basic here. Please help me with that.
Regards,
Kiran
Try out the following:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
exclude-result-prefixes="env xsl">
<xsl:template match="/">
<message>
<send-parameters>
<agent-parameter>
<name>IncidentNumber</name>
<value>
<xsl:value-of select="message/env:Envelope/env:Body/insertResponse/number" />
</value>
</agent-parameter>
</send-parameters>
</message>
</xsl:template>
</xsl:stylesheet>
As stated by Micheal you are missing namespace definition in your stylesheet. Once you do that your code is good to go

xslt not showing results. xpath or ns wrong?

i have the following xml and xslt to render it, but got no results. I checked again and again and see not path problem, and the xsl went through the compiler. so I am not sure if it's namespace problem or something else. many thx!
XML file
<?xml version="1.0" encoding="UTF-8"?>
<bibdataset xsi:schemaLocation="http://www.elsevier.com/xml/ani/ani http://www.elsevier.com/xml/ani/embase_com.xsd"
xmlns="http://www.elsevier.com/xml/ani/ani"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ce="http://www.elsevier.com/xml/ani/common"
xmlns:ait="http://www.elsevier.com/xml/ani/ait">
<item>
<bibrecord>
<item-info>
<itemidlist><ce:doi>10.1258/0268355042555000</ce:doi>
</itemidlist>
</item-info>
<head>
<citation-title>
<titletext xml:lang="en" original="y">Effect of seasonal variations on the emergence of deep venous thrombosis of the lower extremity
</titletext>
</citation-title>
<abstracts>
<abstract xml:lang="en" original="y">
<ce:para>Objective: We aimed to determine the role of seasonal and meteorological variations in the incidence of lower extremity
</ce:para>
</abstract>
</abstracts>
</head>
</bibrecord>
</item>
</bibdataset>
XSLT file
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.elsevier.com/xml/ani/ani"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ce="http://www.elsevier.com/xml/ani/common"
xmlns:ait="http://www.elsevier.com/xml/ani/ait">
<xsl:output indent="yes" omit-xml-declaration="no"
media-type="application/xml" encoding="UTF-8" />
<xsl:template match="/">
<searchresult>
<xsl:apply-templates
select="/bibdataset/item/bibrecord" />
</searchresult>
</xsl:template>
<xsl:template match="bibrecord">
<document>
<title><xsl:value-of select="head/citation-title/titletext" /></title>
<snippet>
<xsl:value-of select="head/abstracts/abstract/ce:para" />
</snippet>
<url>
<xsl:variable name="doilink" select="item-info/itemidlist/ce:doi"/>
<xsl:value-of
select="concat('http://dx.doi.org/', $doilink)" />
</url>
</document>
</xsl:template>
</xsl:stylesheet>
This is indeed an issue with namespaces. In your XML, you have declared a default namespace meaning the root element, and all its descendants, and in this namespace.
<bibdataset .xmlns="http://www.elsevier.com/xml/ani/ani" ...
Now, in your XSLT, you have also declared this namespace, but without a prefix.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.elsevier.com/xml/ani/ani"
This means it only applies to the elements you are outputting, so your searchresult element gets output in this namespace
<searchresult xmlns="http://www.elsevier.com/xml/ani/ani"
However, it doesn't apply to the xpath expression in your XSLT, and so these are looking for elements in your input XML with no namespace.
In XSLT 2.0 the solution would be to simply declare an "xpath-default-namespace"
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.elsevier.com/xml/ani/ani"
xpath-default-namespace="http://www.elsevier.com/xml/ani/ani" ...
In XSLT 1.0, you will have to declare the namespace with a prefix, and use this prefix in all the xpath expressions.
Try this XSLT
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.elsevier.com/xml/ani/ani"
xmlns:ani="http://www.elsevier.com/xml/ani/ani"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ce="http://www.elsevier.com/xml/ani/common"
xmlns:ait="http://www.elsevier.com/xml/ani/ait"
exclude-result-prefixes="ani">
<xsl:output indent="yes" omit-xml-declaration="no"
media-type="application/xml" encoding="UTF-8" />
<xsl:template match="/">
<searchresult>
<xsl:apply-templates
select="/ani:bibdataset/ani:item/ani:bibrecord" />
</searchresult>
</xsl:template>
<xsl:template match="ani:bibrecord">
<document>
<title><xsl:value-of select="ani:head/ani:citation-title/ani:titletext" /></title>
<snippet>
<xsl:value-of select="ani:head/ani:abstracts/ani:abstract/ce:para" />
</snippet>
<url>
<xsl:variable name="doilink" select="ani:item-info/ani:itemidlist/ce:doi"/>
<xsl:value-of
select="concat('http://dx.doi.org/', $doilink)" />
</url>
</document>
</xsl:template>
</xsl:stylesheet>
Note that you can remove the line xmlns="http://www.elsevier.com/xml/ani/ani" but that would mean your searchresult (and other) elements would be output with no namespace, so you would need to output it as <ani:searchresult> if you wanted it in the given namespace.

Format-number from ###.0 to ###.00

I working with a project in BizTalk where use xslt to convert from and edifact file to an UBL file.
The edifact file contains price values of ###.0 and that do not work. I want to change it to ###.00 using format-number. But I cannot make it work.
This is what I have made so far:
<cbc:Value>
<xsl:variable name="SumOfNodes" select="edi:PRI/edi:C509/C50902"/>
<xsl:value-of select="format-number($SumOfNodes, '0.00')"/>
</cbc:Value>
I am using this stylesheet:
<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:edi="http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006/MEDIAMARKT"
xmlns:ubl="urn:oasis:names:specification:ubl:schema:xsd:Order-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
exclude-result-prefixes="msxsl edi">
Any ideas on how to solve this??
This may be due to undeclared namespace in your XSLT. Please check whether namespaces are declared correctly in your XSLT. Unless you show the full XSLT coding with XML coding, we cannot able to provide solution. However please refer the below Sample XML and XSLT with the output
XSLT:
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="chapter">
<Value>
<xsl:variable name="num" select="number"/>
<xsl:value-of select="format-number($num,'00.00')"/>
</Value>
</xsl:template>
</xsl:stylesheet>
Sample XML
<?xml version="1.0"?>
<chapter>
<number>45</number>
</chapter>
Output
<?xml version='1.0' ?>
<Value>45.00</Value>

How to select the value from an attribute that has a colon in xslt?

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>