Mapping with BizTalk + Multiple nodes to a single one - biztalk

I'm trying to make a mapping with this xml:
<rootxml>
<documents>
<document>
<iddoc>1</iddoc>
<total_price>1000</total_price>
</document>
</documents>
<items>
<item>
<iddoc>1</iddoc>
<iditem>1</iditem>
<quantity>1</quantity>
<price>800</price>
</item>
<item>
<iddoc>1</iddoc>
<iditem>2</iditem>
<quantity>1</quantity>
<price>200</price>
</item>
</items>
<taxes>
<tax>
<iddoc>1</iddoc>
<iditem>1</iditem>
<idtax>1000</idtax>
<value>123.90</value>
<tax>
<tax>
<iddoc>1</iddoc>
<iditem>2</iditem>
<idtax>1000</idtax>
<value>34.13</value>
<tax>
</taxes>
</rootxml>
to this one:
<resultxml>
<documento>
<iddoc>1</iddoc>
<total_price>1000</total_price>
<items>
<item>
<iddoc>1</iddoc>
<iditem>1</iditem>
<quantity>1</quantity>
<price>800</price>
<taxes>
<idtax>1000</idtax>
<value>123.90</value>
</taxes>
</item>
<item>
<iddoc>1</iddoc>
<iditem>2</iditem>
<quantity>1</quantity>
<price>200</price>
<taxes>
<tax>
<idtax>1000</idtax>
<value>34.13</value>
<tax>
</taxes>
</item>
</items>
</documento>
</resultxml>
I can't find out how to solve this. Although the original xml document can have several documents it will always have one, so I have to merge the items into it and taxes into its respective item.
Thank you

I think you'll have to write a chunk of custom-XSLT. Loop through items/item and then build an xpath to taxes/tax[where iditem=$itemId]. The trick is to get the first itemId into the variable.
Sorry, I have limited time right now, cannot create a full working demo for you.
Here's the related issue I had a while back:
http://www.stylusstudio.com/ssdn/default.asp?action=9&fid=48&read=7896
Neal Walters

Related

creating DropdownList

Consider the following XML file:
<?xml version="1.0" encoding="utf-8"?>
<warehouse>
<cat id="computer">
<item>
<SN>1</SN>
<name>Toshiba</name>
<quantity>12</quantity>
<description>CPU: CORE I5 RAM: 3 GB HD: 512 GB</description>
<price>400 USD</price>
</item>
<item>
<SN>2</SN>
<name>Dell</name>
<quantity>14</quantity>
<description>CPU: CORE I5 RAM: 3 GB HD: 512 GB</description>
<price>300 USD</price>
</item>
<item>
<SN>3</SN>
<name>Dell</name>
<quantity>14</quantity>
<description>CPU: CORE I5 RAM: 3 GB HD: 512 GB</description>
<price>300 USD</price>
</item>
<item>
<SN>5</SN>
<name>Dell</name>
<quantity>14</quantity>
<description>CPU: CORE I5 RAM: 3 GB HD: 512 GB</description>
<price>300 USD</price>
</item>
<item>
<SN>6</SN>
<name>Dell</name>
<quantity>14</quantity>
<description>CPU: CORE I5 RAM: 3 GB HD: 512 GB</description>
<price>300 USD</price>
</item>
<item>
<SN>8</SN>
<name>Toshiba</name>
<quantity>13</quantity>
<description>CPU: CORE I5 RAM: 5 GB HD: 512 GB3</description>
<price>400 USD</price>
</item>
<item>
<SN>9</SN>
<name>Toshiba</name>
<quantity>13</quantity>
<description>CPU: CORE I5 RAM: 5 GB HD: 512 GB3</description>
<price>400 USD</price>
</item>
<item>
<SN>dsfdSF</SN>
<name>fsdfsD</name>
<quantity>dsfdSFS</quantity>
<description>FSDFS</description>
<price>FSDFSD</price>
</item>
<item>
<SN>dsfdSF</SN>
<name>fsdfsD</name>
<quantity>dsfdSFS</quantity>
<description>FSDFS</description>
<price>FSDFSD</price>
</item>
<item>
<SN>alia</SN>
<name>alia</name>
<quantity>alia</quantity>
<description>alia</description>
<price>alia</price>
</item>
</cat>
<cat id="Stationery">
<item>
<SN> 1 </SN>
<name>note books</name>
<quantity>250</quantity>
<description>Caterpiller</description>
<price>5 USD</price>
</item>
<item>
<SN> 2 </SN>
<name> pencils </name>
<quantity> 300 </quantity>
<description> Caterpiller </description>
<price> 2 USD </price>
</item>
<item>
<SN> 3 </SN>
<name> note books </name>
<quantity> 250 </quantity>
<description> Caterpiller </description>
<price> 5 USD </price>
</item>
<item>
<SN>4</SN>
<name>pencils</name>
<quantity>45</quantity>
<description>Pilot</description>
<price>4 USD</price>
</item>
<item>
<SN>5</SN>
<name>pencils</name>
<quantity>45</quantity>
<description>Pilot</description>
<price>4 USD</price>
</item>
<item>
<SN>6</SN>
<name>pencils</name>
<quantity>45</quantity>
<description>Pilot</description>
<price>4 USD</price>
</item>
<item>
<SN>7</SN>
<name>sdfsdfsdfsdfsd</name>
<quantity>sdfsdf</quantity>
<description>dsfsdfs</description>
<price>sdfsdf</price>
</item>
<item>
<SN>8</SN>
<name>pencils</name>
<quantity>45</quantity>
<description>Pilot</description>
<price>4 USD</price>
</item>
<item>
<SN>9</SN>
<name>books</name>
<quantity>250</quantity>
<description>chinses</description>
<price>3 USD</price>
</item>
<item>
<SN>alia</SN>
<name>alia</name>
<quantity>alia</quantity>
<description>alia</description>
<price>alia</price>
</item>
</cat>
<cat id="Furniture">
<item>
<SN> 1 </SN>
<name>dasd</name>
<quantity>asdasd</quantity>
<description>das</description>
<price>dasd</price>
</item>
<item>
<SN> 2 </SN>
<name> chairs </name>
<quantity> 18 </quantity>
<description> European Type</description>
<price> 150 USD </price>
</item>
<item>
<SN>3</SN>
<name>Tabels</name>
<quantity>12</quantity>
<description>European Type</description>
<price>50 USD</price>
</item>
<item>
<SN>4</SN>
<name>Tabels</name>
<quantity>12</quantity>
<description>European Type</description>
<price>50 USD</price>
</item>
<item>
<SN>5</SN>
<name>Tabels</name>
<quantity>12</quantity>
<description>European Type</description>
<price>50 USD</price>
</item>
<item>
<SN>6</SN>
<name>Tabels</name>
<quantity>12</quantity>
<description>European Type</description>
<price>50 USD</price>
</item>
<item>
<SN>7</SN>
<name>Tabels</name>
<quantity>12</quantity>
<description>European Type</description>
<price>50 USD</price>
</item>
<item>
<SN>8</SN>
<name>Tabels</name>
<quantity>12</quantity>
<description>European Type</description>
<price>50 USD</price>
</item>
<item>
<SN>alia</SN>
<name>alia</name>
<quantity>alia</quantity>
<description>alia</description>
<price>alia</price>
</item>
</cat>
</warehouse>
I need to create a drop down list. The drop down list has to display all the values of <SN> where <cat id="computer"> only.
How can this be done using LINQ or DataView or Xpath?
How about this?
XmlDocument doc = new XmlDocument();
doc.Load(#"~/XML/XML.xml");
var nodes = doc.SelectNodes("warehouse/cat[#id='computer']/item/SN");
myDropDown.DataTextField = "InnerText";
myDropDown.DataValueField = "InnerText";
//now bind the dropdownlist to the dataview
myDropDown.DataSource = nodes;
myDropDown.DataBind();
Load the xml into an XElement:
var xml = XElement.Load("test.xml");
Execute XPath to select the SN elements in the cats with id computer: (+ put them in a list)
var snValues = xml.XPathSelectElements("//cat[#id='computer']/item/SN")
.Select(x => x.Value).ToList();
Required usings:
using System.Linq;
using System.Xml.Linq;
using System.Xml.XPath;

Asp.net vb find XML nodes

i have the below xml and i want to get the phone from each item.
I have a loop where i can read the name and surname with success but i'm stacked on the other part.
Which is the xpath i should follow
<items>
<item>
<name></name>
<surname></surname>
<list>
<phone></phone>
<email></email>
</list>
</item>
<item>
<name></name>
<surname></surname>
<list>
<phone></phone>
<email></email>
</list>
</item>
</items>
Thanks
dom.xpath("//item").each do |item_node|
name = item_node.xpath("./name")
surname = item_node.xpath("./surname")
phone = item_node.xpath("./list/phone")
email = item_node.xpath("./list/email")
end

Mapping related repeating node to a repeating node on BizTalk Mapper

I'm trying to do a map on BizTalk 2013, and I'm blocked at this mapping problem (using mapper):
Input message:
<DetailsResponse>
<HeaderDetails>
<DocumentNumber>322</DocumentNumber>
</HeaderDetails>
<ItemDetails>
<item>
<DocumentNumber>322</DocumentNumber>
<ItemNumber>1</ItemNumber>
<MaterialNumber>40</MaterialNumber>
<Description>random description 1</Description>
</item>
<item>
<DocumentNumber>322</DocumentNumber>
<ItemNumber>2</ItemNumber>
<MaterialNumber>41</MaterialNumber>
<Description>random description 2</Description>
</item>
</ItemDetails>
<ScheduleDetails>
<item>
<DocumentNumber>322</DocumentNumber>
<ItemNumber>1</ItemNumber>
<ConfirmedQuantity>2.000</ConfirmedQuantity>
</item>
<item>
<DocumentNumber>322</DocumentNumber>
<ItemNumber>2</ItemNumber>
<ConfirmedQuantity>3.000</ConfirmedQuantity>
</item>
</ScheduleDetails>
</DetailsResponse>
Intended output message:
<Response>
<Data>
<Items>
<Item>
<LineNumber>
<Internal>1</Internal>
</LineNumber>
<ConfirmedQuantity>
<Value>2</Value>
</ConfirmedQuantity>
<Article>
<Number>40</Number>
<Description>random description 1</Description>
</Article>
</Item>
<Item>
<LineNumber>
<Internal>2</Internal>
</LineNumber>
<ConfirmedQuantity>
<Value>3</Value>
</ConfirmedQuantity>
<Article>
<Number>41</Number>
<Description>random description 2</Description>
</Article>
</Item>
</Items>
</Data>
</Response>
I want to map ItemsDetails and ScheduleDetails to Item, by "merging" their data based on ItemNumber. I already tried a lots of things but wasn't able to do it yet.
I couldn't find any example about this.Does this pattern have any particular name?
If anyone has any idea that they can share, it would be appreciated.
The only way I can think to maybe get this working with Functoids is to link ItemDetails and ScheduleDetails with one or more Looping Functoids and using an Equal Functoid to filter the ScheduleDetails based on the current ItemDetail ItemNumber.
It that doesn't work out, your only other option is custom Xslt. A Call Template would be pretty straight forward.
If you convert your map to vanilla XSLT, then the mapping becomes straightforward :
<?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" indent="yes"/>
<xsl:key name="itemSchedules"
match="/DetailsResponse/ScheduleDetails/item"
use="concat(DocumentNumber,'-',ItemNumber)" />
<xsl:template match="/DetailsResponse">
<Response>
<Data>
<Items>
<xsl:apply-templates select="ItemDetails/item" />
</Items>
</Data>
</Response>
</xsl:template>
<xsl:template match="item">
<Item>
<LineNumber>
<Internal>
<xsl:value-of select="ItemNumber"/>
</Internal>
</LineNumber>
<ConfirmedQuantity>
<Value>
<xsl:value-of select="format-number(key('itemSchedules',
concat(DocumentNumber,'-',ItemNumber))/ConfirmedQuantity,0)" />
</Value>
</ConfirmedQuantity>
<Article>
<Number>
<xsl:value-of select="MaterialNumber"/>
</Number>
<Description>
<xsl:value-of select="Description"/>
</Description>
</Article>
</Item>
</xsl:template>
</xsl:stylesheet>
The xsl:key retains an index of references to the schedule details 'part' of the puzzle, and we create a catenated key of DocumentNumber and ItemNumber.

How to filter XML elements using LINQ query for one attribute/field containing a particular substring?

Example:
<Item name="item1">
<mode = "ax, bx" />
</Item>
<Item name="item2">
<mode = "bx, cx" />
</Item>
<Item name="item3">
<mode = "cx, dx" />
</Item>
In the example above I would like to extract all the items with modes containing "cx".
Thanks in advance!
Your XML in the example is not well formed. Assuming you meant:
<Items>
<Item name="item1">
<mode>ax, bx</mode>
</Item>
<Item name="item2">
<mode>bx, cx</mode>
</Item>
<Item name="item3">
<mode>cx, dx</mode>
</Item>
</Items>
you can do:
var els=from el in XDocument.Parse(inxml).Descendants("Item")
where el.Element("mode").Value.Contains("bx")
select el;
That is not legal XML (mode is an element name, you can set it equal to a string), but you should be able to do something like this, assuming that the string you are matching is the element value:
doc.Descendants("Item").Where( item => item.Elements("mode").Any( mode => mode.Value.Contains("cx")));
Assuming a well formed XML doc:
<Items>
<Item name="item1">
<mode>ax, bx</mode>
</Item>
<Item name="item2">
<mode>bx, cx</mode>
</Item>
<Item name="item3">
<mode>cx, dx</mode>
</Item>
</Items>
Do something like this:
XElement items = XElement.Load(#"C:\items.xml");
var filteredItems = from item in items.Descendants("Item")
where item.Element("mode").Value.Contains("cx")
select item;
foreach (var item in filteredItems)
{
Console.WriteLine(item.FirstAttribute.Value);
}
Output:
item2
item3

asp.net xpath: select only certain attributes

I have a GridView populated from an xml file, which has the following structure:
<menu>
<item id="1" name="home" page="default.aspx">
*{...some stuff...}*
<item>
<item id="2" name="content" page="content.aspx">
*{...some stuff...}*
<item>
<item id="3" name="user" page="user.aspx">
*{...some stuff...}*
<item>
<menu>
As you can reckon, it's the menu of my application.
If i just associate that file to an xmldatasource and then to a GridView, it shows (correctly) a grid like this:
id name page
1 home default.aspx
2 content content.aspx
3 user user.aspx3 user user.aspx
How do I set the xPath query to only show name attribute/field?
I've tried those:
menu/item#name
menu/#name
//#name
but didn't work
I have a GridView populated from an
xml file, which has the following
structure:
<menu>
<item id="1" name="home" page="default.aspx">
*{...some stuff...}*
<item>
<item id="2" name="content" page="content.aspx">
*{...some stuff...}*
<item>
<item id="3" name="user" page="user.aspx">
*{...some stuff...}*
<item>
<menu>
This is not a well-formed XML file -- an ending tag must have the sintax </tag> and there are no ending tags at all in the above text.
How do I set the xPath query to only
show name attribute/field?
I've tried those:
menu/item#name
menu/#name
//#name
is syntactically invalid: location steps must start with the / character and there is no / character between item and #name.
is syntactically valid but is asking to select all name attributes of all menu elements that are children of the current node. Unfortunately, menu has no name attributes.
should select nodes, but given the text above isn't at all a well-formed XML document, this explains the negative result. Also, this selects all name attributes in the whole document, regardles on which element they are -- this is not exactly what you want, regardless of the fact that on a wellformed document of this type this might select the nodes you want.
Solution:
Step1: Correct your XML document:
<menu>
<item id="1" name="home" page="default.aspx">
*{...some stuff...}*
</item>
<item id="2" name="content" page="content.aspx">
*{...some stuff...}*
</item>
<item id="3" name="user" page="user.aspx">
*{...some stuff...}*
</item>
</menu>
Step2: Use one of the following XPath expressions (there are even more that would select the wanted nodes):
/menu/item/#name
or
/*/item/#name
or
/*/*/#name
or
//#name

Resources