Mapping xml string to any type as xml element in BizTalk map - biztalk

I have a BizTalk map that look like this:
The string concat look like this:
when I test this map I get this output:
output
what I need is this output:
enter image description here
Can anyone tell me how I can get the shown output, where the .. tags and all the sub tags is not a string but is xml element tag..? I Need to do this in the shown BizTalk Map!
I have now made a small VS project where you can test and see how to solve my problem. You can download the project from this link:
Visual Studio Project
For the test project map the input is this:
<ns0:SomeData xmlns:ns0="http://CustomSchemaMapping.SourceSchema">
<ID>0</ID>
<NAME>Test Person</NAME>
<YEAR>2022</YEAR>
</ns0:SomeData>
and the output should be like this:
<ns0:OutputData xmlns:ns0="http://CustomSchemaMapping.OutputSchema">
<OtherElement>Test</OtherElement>
<BrevparamXML>
<DATA>
<ID>0</ID>
<NAME>Test Person</NAME>
<YEAR>2022</YEAR>
</DATA>
</BrevparamXML>
</ns0:OutputData>
and NOT like this:
<ns0:OutputData xmlns:ns0="http://CustomSchemaMapping.OutputSchema">
<OtherElement>Test</OtherElement>
<BrevparamXML> <DATA><ID>0</ID><NAME>Test Person</NAME><YEAR>2022</YEAR></DATA>
</BrevparamXML>
</ns0:OutputData>

Is your output schema only used for one integration and you are always going to send the same "Any"-xml? Then I would change the outgoing schema to include those elements. The outgoing xml will be the same anyway and no one else will be affected.

I tried with a Scripting Functoid of type "Inline XSLT Call Template" with following template and got the desired output. Label the inputs ID, NAME and YEAR. You need to tweak my code to get it to validate. Probably add a namespace from SourceSchema.xsd.
XSLT Template
<xsl:template name="MyXsltConcatTemplate">
<xsl:param name="ID" />
<xsl:param name="NAME" />
<xsl:param name="YEAR" />
<xsl:element name="BrevparamXML">
<xsl:element name="DATA">
<xsl:element name="ID">
<xsl:value-of select="$ID" />
</xsl:element>
<xsl:element name="NAME">
<xsl:value-of select="$NAME" />
</xsl:element>
<xsl:element name="YEAR">
<xsl:value-of select="$YEAR" />
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:template>
Result
<ns0:OutputData xmlns:ns0="http://CustomSchemaMapping.OutputSchema">
<OtherElement>Test</OtherElement>
<BrevparamXML>
<DATA>
<ID>2022</ID>
<NAME>0</NAME>
<YEAR>Test Person</YEAR>
</DATA>
</BrevparamXML>
</ns0:OutputData>

Related

How do you populate a dropdownlist using XSLT

I am able to create a downdownlist. However, i am not able to populate anything into it with XML data. Can anyone help me out on this? Thanks!
This is the XML code
<group name="Security / PDPA">
<section name="Control" db_field_name="control_score">
<field is_admin_field="N" required="Y">
<question_title>Verify customer's details when necessary</question_title>
<type>List</type>
<db_field_name>verify_customers_details_when_necessary_control</db_field_name>
<options>
<item score="2">Yes</item>
<item score="0">No</item>
<item score="2">No with reason</item>
</options>
<db_field_length>14</db_field_length>
<additional_comment/>
</field></section></group>
This is the XSLT code
<select name="form">
<xsl:for-each select="form/fieldset/group/section/field/options">
<option>
<xsl:attribute name="value">
<xsl:value-of select="item"/>
</xsl:attribute>
</option>
</xsl:for-each>
</select>
I am assuming you have not shown a full XML, because your Xpath expression in the xsl:for-each is looking for form/fieldset/group/section/field/options, but neither the initial form or fieldset are shown in your XML.
With that in mind, the issue is probably because you are selecting the options element with the xsl:for-each, but there is only one of those. You should be selecting item elements, because it looks like you want to output an <option> tag for each item
<xsl:for-each select="form/fieldset/group/section/field/options/item">
<option>
<xsl:attribute name="value">
<xsl:value-of select="#score"/>
</xsl:attribute>
<xsl:value-of select="." />
</option>
</xsl:for-each>
Or better still, use Attribute Value Templates to shorten the code
<xsl:for-each select="form/fieldset/group/section/field/options/item">
<option value="{#score}">
<xsl:value-of select="." />
</option>
</xsl:for-each>

How to get count of child node for each parent element

Source XML
<?xml version="1.0" encoding="UTF-8"?>
<root>
<parent1>
<child1>P1-Child-01</child1>
<child2>P1-Child-02</child2>
</parent1>
<parent2>
<child3>P2-Child-03</child3>
<child4>P2-Child-04</child4>
<child5>P2-Child-05</child5>
</parent2>
<parent3>
<child6>P2-Child-03</child6>
<child7>P2-Child-04</child7>
</parent3>
</root>
Required output
<root>
<parent1>
<cld1>P1-Child-01</cld1>
<cld2>P1-Child-02</cld2>
</parent1>
<parent2>
<cld3>P2-Child-03</cld3>
<cld4>P2-Child-04</cld4>
</parent2>
</root>
i tried creating an XSLT with below logic:
1. It will get the number of parent elements
2. based on that for each parent element i want to get the number of child elements and based on string concat(chld,$index) i want to create new elements
i.e
replacing
<child1>P1-Child-01</child1>
with
<cld4>P2-Child-04</cld4>
but i stuck no how to get the count of child elements for each parent
current Xslt
<xsl:template match="/">
<xsl:call-template name="parentforloop"></xsl:call-template>
</xsl:template>
<xsl:template name="parentforloop" >
<xsl:param name="index" select ="1" />
<xsl:param name="total" select="count(/*/*)"/>
<xsl:param name="parentName" select="concat('parent',$index)"/>
<xsl:element name="{concat('parent',$index )}">
</xsl:element>
<xsl:if test="not($index=$total)">
<xsl:call-template name="parentforloop">
<xsl:with-param name="index" select="$index+1"></xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
Please help
thank You

Generating a Cross Product from two input schemas using BizTalk Map

I am using a many to one mapping in BizTalk, to generate an output schema with data generated using a cross product logic on a node of input schemas.
Following figure depicts what I've done yet:
The sample input xmls are as follows:
<!-Schema1 Instance-->
<Root>
<Data>
<ItemCode>10</ItemCode>
<ItemCost>1024</ItemCost>
</Data>
<Data>
<ItemCode>20</ItemCode>
<ItemCost>2048</ItemCost>
</Data>
</Root>
<!-Schema2 Instance-->
<Root>
<Data>
<Code>10</Code>
<ShipAddr>addr11101</ShipAddr>
</Data>
<Data>
<Code>30</Code>
<ShipAddr>addr33301</ShipAddr>
</Data>
<Data>
<Code>20</Code>
<ShipAddr>addr22201</ShipAddr>
</Data>
<Data>
<Code>10</Code>
<ShipAddr>addr11102</ShipAddr>
</Data>
</Root>
The required output is based on a cross product performed based on equality of Schema1.ItemCode and Schema2.Code. Sample is as follows:
<!--Output Schema Instance required; Order of records is irrelevant-->
<Root>
<Data>
<Code>10</Code>
<ItemCost>1024</ItemCost>
<ShipAddr>addr11101</ShipAddr>
</Data>
<Data>
<Code>20</Code>
<ItemCost>2048</ItemCost>
<ShipAddr>addr22201</ShipAddr>
</Data>
<Data>
<Code>10</Code>
<ItemCost>1024</ItemCost>
<ShipAddr>addr11102</ShipAddr>
</Data>
</Root>
Actual output:
Output with no looping functoid
XML Output
<ns0:Root xmlns:ns0="http://TestTO_DELETE.SchemaOut">
<Data>
<Code>10</Code><ItemCost>1024</ItemCost><ShipAddr>addr11101</ShipAddr>
</Data>
<Data><Code>20</Code></Data>
</ns0:Root>
Output with both looping functoids connections 1, and 2
XML Output
<ns0:Root xmlns:ns0="http://TestTO_DELETE.SchemaOut">
<Data>
<Code>10</Code>
</Data>
<Data>
<Code>20</Code>
</Data>
<Data />
<Data />
<Data />
<Data />
</ns0:Root>
Output with single looping functoid connection 1
XML Output
<ns0:Root xmlns:ns0="http://TestTO_DELETE.SchemaOut">
<Data>
<Code>10</Code><ItemCost>1024</ItemCost><ShipAddr>addr11101</ShipAddr>
</Data>
<Data>
<Code>20</Code>
</Data>
</ns0:Root>
Please suggest how to proceed in such scenario?
I tried various combinations of functoids to get the required output schema, but nothing worked. So, I finally moved on to use scripting functoid, which served my purpose. I am posting my finding as it could be helpful to someone else.
This is how I proceeded:
Remove all connections and functoids from the map
Add a scripting functoid
Connect InputMesagePart_0 to input of scripting functoid
Connect Scripting functoid to the first element node of the output schema
In the Script Functoid Configuration, add the transformation logic. For e.g., in my case the logic was:
<xsl:template name="Template1">
<xsl:param name="MessagePart_0_Xml" /> <!--Not used anywhere-->
<xsl:variable name="Msg_0_RootNode" select="/*[local-name()='Root']/*[local-name()='InputMessagePart_0']/*[local-name()='Root']" />
<xsl:variable name="Msg_1_RootNode" select="/*[local-name()='Root']/*[local-name()='InputMessagePart_1']/*[local-name()='Root']" />
<xsl:for-each select="$Msg_0_RootNode/Data">
<xsl:variable name="Msg_0_DataNode" select="." />
<xsl:for-each select="$Msg_1_RootNode/Data">
<xsl:variable name="Msg_1_DataNode" select="." />
<xsl:if test="$Msg_0_DataNode/ItemCode/text() = $CostCenterDataNode/Code/text()">
<ItemCost>
<xsl:value-of select="$Msg_0_DataNode/ItemCost/text()" />
</ItemCost>
<ShipAddr>
<xsl:value-of select="$CostCenterDataNode/ShipAddr/text()" />
</ShipAddr>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
If there is a better way to approach this problem, please suggest.

BizTalk Map, Prevent Looping For-Each

In the source XSD of the following map, InvTransTable and ToWarehouse elements are unbounded.
I want to map values only for the first iteration in each case. My problem is, the XSLT generated by the map contains two loops, as can be seen in the following:
<ns0:Record>
<xsl:for-each select="s1:InvTransTable">
<xsl:variable name="var:v4" select="position()" />
<xsl:for-each select="s1:ToWarehouse">
<xsl:variable name="var:v5" select="position()" />
<xsl:variable name="var:v6" select="userCSharp:LogicalEq(string($var:v5) , "1")" />
<xsl:variable name="var:v7" select="userCSharp:LogicalEq(string($var:v4) , "1")" />
<xsl:variable name="var:v8" select="userCSharp:LogicalAnd(string($var:v6) , string($var:v7))" />
<xsl:variable name="var:v12" select="userCSharp:StringUpperCase("B")" />
<xsl:variable name="var:v13" select="userCSharp:StringUpperCase("M")" />
<xsl:variable name="var:v14" select="userCSharp:StringUpperCase("4")" />
<ns0:Header>
<xsl:if test="string($var:v8)='true'">
<xsl:variable name="var:v9" select="s1:EXDRefCustAccount/text()" />
<ns0:AccountNo>
<xsl:value-of select="$var:v9" />
</ns0:AccountNo>
</xsl:if>
<xsl:if test="string($var:v7)='true'">
<xsl:variable name="var:v10" select="../s1:ShipDate/text()" />
<ns0:DateExpected>
<xsl:value-of select="$var:v10" />
</ns0:DateExpected>
</xsl:if>
This results in the created XML containing multiple header elements, which is not what I want!
I've tried to prevent this throug the use of Iteration (checking for a value of 1) and Conditional functoids but this hasn't worked. Can anyone please advise how I can achieve what is needed without resorting to a scripting functoid or replacing the map with XSLT?
If you know you only need to map the first instance of each, use the Index functoid with an index of 1, instead of the Iteration functoid.

How do I bind xml file to dropdownlist using XML datasource?

How to bind xml file to asp.net dropdownlist using xmldatasource? If I do it like below, I see empty dropdownlist.
ASP.NET
<asp:DropDownList runat="server" ID="ddlDEMO" DataValueField="BILLAB" DataTextField="BILLAB" DataSourceID="xdsDemo">
</asp:DropDownList>
<asp:XmlDataSource ID="xdsDemo" runat="server" DataFile="~/XML/Bills.xml"
XPath="/Bills/Bill"></asp:XmlDataSource>
XML:
<?xml version="1.0" encoding="utf-8" ?>
<Bills>
<Bill>
<BILLID>1</BILLID>
<BILLAB>ONE</BILLAB>
</Bill>
</Bills>
It is working for attributes, not elements. This would have work if your XML looked like that:
<?xml version="1.0" encoding="utf-8" ?>
<Bills>
<Bill BILLID="1" BILLAB="ONE">
</Bill>
</Bills>
You can use transformation to fix it. Look here:
http://kanakaiah.wordpress.com/2008/05/06/using-xslt-files-with-the-new-xmldatasource-control/
Based on the solution in that link you should write xsl like that:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Bills">
<Bills>
<xsl:apply-templates select="Bill"/>
</Bills>
</xsl:template>
<xsl:template match="Bill">
<Bill>
<xsl:attribute name="BILLID">
<xsl:value-of select="BILLID"/>
</xsl:attribute>
<xsl:attribute name="BILLAB">
<xsl:value-of select="BILLAB"/>
</xsl:attribute>
</BILL>
</xsl:template>
</xsl:stylesheet>
I would either create a class or a structure and serialize/deserialize from/to xml to my class/struct. Here is how you serialize your xml documents:
http://support.microsoft.com/kb/815813
After this I create a generic List of my class/struct and it is much easier to bind to anything and manipulate in general.
Good luck.

Resources