BizTalk - adding namespace to xml - xslt

I'm new to BizTalk and I'm having problems with adding a namespace to my output file.
I need to get the following output, with the namespace at the root level:
<?xml version="1.0" encoding="utf-8"?>
<TestExternalPO xmlns="http://Test.EDI.TestExternalPO.Schemas">
<Routing/>
<POHeader/>
</TestExternalPO>
My xsd is:
<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:b="http://schemas.microsoft.com/BizTalk/2003"
elementFormDefault="qualified" version="1.0">
<xs:annotation>
<xs:appinfo>
<b:schemaInfo BizTalkServerEditorTool_Version="1.5" root_reference="TestExternalPO"
displayroot_reference="TestExternalPO" standard="XML"
targetNamespace="http://Test.EDI.TestExternalPO.Schemas"
xmlns:b="http://schemas.microsoft.com/BizTalk/2003" />
</xs:appinfo>
</xs:annotation>
My xslt is:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:apply-templates select="TestExternalPO"/>
</xsl:template>
<xsl:template match="TestExternalPO">
<TestExternalPO xmlns="http://Test.EDI.TestExternalPO.Schemas">
<Routing>....
Any help greatly appreciated,
Maggs
Update 25-Apr.
Thanks for all the comments.
The above setup works but doesn't give me what I want i.e namespace at root level.
I did test the namespace in the xslt but got an error on BizTalk.
<xsl:template match="TestExternalPO">
<TestExternalPO xmlns="http://Test.EDI.TestExternalPO.Schemas">
<Routing>
<xsl:attribute name="SendPartner">
BizTalk Error - Finding the document specification by message type "http://Test.EDI.TestExternalPO.Schemas" failed. Verify the schema deployed properly.
Below is structure of input file:
<TestExternalPO>
<POHeader>
</POHeader>
<TradingPartnersList>
<TradingPartners>
</TradingPartners>
</TradingPartnersList>
<Contract>
</Contract>
<ItemsList>
<Items>
</Items>
</ItemsList>
</TestExternalPO>
The problem is with my declaration of 'xmlns'.
If I add 'targetNamespace', then output has the targetNamespace at the root element.
This works:
<xsl:template match="TestExternalPO">
<TestExternalPO targetNamespace="http://Test.EDI.TestExternalPO.Schemas">
<Routing>
<xsl:attribute name="SendPartner">
Again thanks for the help.
Maggs

Here's how your xslt should look. You want to exclude namespace so add the prefix to exclude-result-prefixes
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="ns0"
xmlns:ns0="http://Test.EDI.TestExternalPO.Schemas">
<xsl:template match="/">
<xsl:apply-templates select="TestExternalPO"/>
</xsl:template>
<xsl:template match="TestExternalPO">
<ns0:TestExternalPO>
<Routing>....

Related

How to add namespace and xsi to the Incoming XML with no namespace

I have requirement where I have to add Namespace and xsi to the
element from the source xml with No Namespace.
In Source XML I am just getting the Nodes and there is No namespace
and another program needs BizTalk to add Namespace and XSI to the XML for its processing.
I tried:
Used add namespace pipeline component. (It just added
namespace and not the xsi bits)
Used Map for putting up the desired format and yes no luck as got
just the namespace.
Need your help around this.
My source XML is like
<?xml version="1.0" encoding="UTF-16"?>
<Document>
<CstmrPmtStsRpt>
<GrpHdr>
<MsgId></MsgId>
<CreDtTm></CreDtTm>
<InitgPty>
<Id>
<OrgId>
<BICOrBEI></BICOrBEI>
</OrgId>
</Id>
</InitgPty>
</GrpHdr>
<OrgnlGrpInfAndSts>
<OrgnlMsgId></OrgnlMsgId>
<OrgnlMsgNmId></OrgnlMsgNmId>
<OrgnlNbOfTxs></OrgnlNbOfTxs>
<OrgnlCtrlSum></OrgnlCtrlSum>
<GrpSts>ACCP</GrpSts>
</OrgnlGrpInfAndSts>
</CstmrPmtStsRpt>
</Document>
My Required format is as below:
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="MyNamespace">
<CstmrPmtStsRpt>
<GrpHdr>
<MsgId></MsgId>
<CreDtTm></CreDtTm>
<InitgPty>
<Id>
<OrgId>
<BICOrBEI></BICOrBEI>
</OrgId>
</Id>
</InitgPty>
</GrpHdr>
<OrgnlGrpInfAndSts>
<OrgnlMsgId></OrgnlMsgId>
<OrgnlMsgNmId></OrgnlMsgNmId>
<OrgnlNbOfTxs></OrgnlNbOfTxs>
<OrgnlCtrlSum></OrgnlCtrlSum>
<GrpSts>ACCP</GrpSts>
</OrgnlGrpInfAndSts>
</CstmrPmtStsRpt>
</Document>
Use the namespace attribute of xsl:element like this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="*">
<xsl:element name="{local-name()}" namespace="MyNamespace">
<xsl:namespace name="xsi" select="'http://www.w3.org/2001/XMLSchema-instance'"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Edit: Since you need to work with XSLT-1.0. Use following stylesheet:
<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/Document">
<Document xmlns="MyNamespace"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:apply-templates/>
</Document>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}" namespace="MyNamespace">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Note, that you need to know your rootnode's name for this (in this case Document).
BizTalk Answer:
First, it's a good thing the incoming document has no namespace. Xml Namespaces are far, far, far more trouble than they're worth and should be avoided/removed whenever possible.
Second the output format is not valid Xml. "MyNamespace" is not a valid URI and can't be used for a Namespace. If this is what they are asking for, they need to fix that first.
But, if you must, your process should not be "add a namespace". What you're really doing is Transforming from SysA's Document to SysB's Document. For that, use a Map. You will use to practially identical Schemas, one with and one without the Target Namespace.
The Mapper will handle xsi for you as well, if it's needed.

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!

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>

XSLT transform error

I have the following xml:
<RootNode xmlns="http://someurl/path/path/path">
<Child1>
<GrandChild1>Value</GrandChild1>
<!-- Lots more elements in here-->
</Child1>
</RootNode>
I have the following xslt:
<xsl:stylesheet version="1.0" xmlns="http://someurl/path/path/path" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1>
<xsl:for-each select="RootNode/Child1">
<NewNodeNameHere>
<xsl:value-of select="GrandChild1"/>
</NewNodeNameHere>
<!-- lots of value-of tags in here -->
</xsl:for-each>
</NewChild1>
</NewRootNode >
</xsl:template>
</xsl:stylesheet>
The problem: this is the my result:
<?xml version="1.0" encoding="utf-8"?>
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1 />
</NewRootNode>
I am expecting to see:
<?xml version="1.0" encoding="utf-8"?>
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1>
<NewNodeNameHere>Value</NewNodeNameHere>
<!-- Other new elements with values from the xml file -->
</NewChild1>
</NewRootNode>
I am missing of the information inside of NewChild1 that should be there.
I think my for-each select is correct, so the only thing I can think of is that there is a problem with the namespace in the Xml and the namespace in the xslt. Can anybody see what I'm doing wrong?
The problem is caused by the namespaces.
Since the xml defines xmlns="http://someurl/path/path/path", it is not in the default namespace anymore.
You can define that namespace with an name like xmlns:ns="http://someurl/path/path/path" in the xsl, and then use that name in the XPath expression.
The following works for me:
<xsl:stylesheet version="1.0" xmlns:ns="http://someurl/path/path/path" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1>
<xsl:for-each select="ns:RootNode/ns:Child1">
<NewNodeNameHere>
<xsl:value-of select="ns:GrandChild1"/>
</NewNodeNameHere>
<!-- lots of value-of tags in here -->
</xsl:for-each>
</NewChild1>
</NewRootNode >
</xsl:template>
</xsl:stylesheet>
The stylesheet namespace should be http://www.w3.org/1999/XSL/Transform instead of http://someurl/path/path/path.
Also, since the input XML uses a namespace all your XPath expressions should be namespace-qualified:
<xsl:template match="/" xmlns:ns1="http://someurl/path/path/path">
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1>
<xsl:for-each select="ns1:RootNode/ns1:Child1">
<NewNodeNameHere>
<xsl:value-of select="ns1:GrandChild1"/>
</NewNodeNameHere>
<!-- lots of value-of tags in here -->
</xsl:for-each>
</NewChild1>
</NewRootNode>
</xsl:template>

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>