We are using XSLT to display xml attributes depending upon their value. We are able to do it from server side using C#. But we are not getting how to achieve it through XSLT.
We are using sample xml as;
<BookInfo>
<BookTable show="Book 1" >
<book id="book1" value="Book 1" />
<book id="book2" value="Book 2" />
</BookTable>
</BookInfo>
We want to read "show" attribute value and depending upon the value, we want to display the node information.
Please help me to achieve this using XSLT.
Thanks in advance.
Modified xml;
<Book>
<Info>
<Item name="Item1" type="DropDown" defaultValue="Two" values="One,Two,Three" />
<Item name="One" type="Label" value="some text" />
<Item name="Two" type="TextBox" value="another text" />
<Item key="Three" name="CheckBox" value="true" />
</Info>
</Book>
Unfortunately the xml format got changed. Now, in this case, for Item1 defaultValue is two, so node with name "two" should be returned.
It's something like:
<xsl:template match="BookTable">
<xsl:value-of select="book[#value = current()/#show]"/>
</xsl:template>
EDIT
Your second example isn't quite clear, I'm assuming there is always a <Item name="Item1"> node, that points to the real node that should be displayed.
<xsl:template match="Info">
<xsl:copy-of select="Item[#name = Item[#name='Item1']/#defaultValue]" />
</xsl:template>
In the XPath you need a # to get at the value of an attribute of your input-xml.
The Item[#name = ...] selects an item where the value of the name attribute equals the specified value.
The current() gives access to the current node that the template is processing. You need that as a plain #show would select the value of that attribute for the node being selected. Example: an Item[#name = #defaultValue] would select Items where the values for 'name' and 'defaultValue' are identical.
Related
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>
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.
I am using BaseX to store XML data with multiple item nodes in the following format:
<root>
<item id="Root" parent_id="0" type="folder">
<content>
<name>Root</name>
</content>
</item>
<item id="One" parent_id="Root" type="file">
<content>
<name>First File in the Tree</name>
</content>
</item>
<item id="Two" parent_id="Root" type="file">
<content>
<name>Second File in the Tree</name>
</content>
</item>
</root>
I am trying to update the parent_id on one of the 'item' nodes to another item node's id attribute.
The tree before running the XQuery expression:
Root
∟ First File in the Tree
∟ Second File in the Tree
I am trying to figure out the correct XQuery expression to change the parent of one of the items from root to "one" item, so that my tree now looks like this:
Expected result tree:
Root
∟ First File in the Tree
∟ Second File in the Tree
Since the attribute parent_id controls this, I am looking to update exactly that.
If all you want to do is to update the #parent_id attribute, use a simple updating query like
replace value of node //item[#id='Two']/#parent_id with 'One'
But: this wouldn't actually change the XML tree, but only the one you're representing in XML (although I believe that this is what your question was about). A more XML-like approach to store the tree would be directly mapping the tree you want to have to XML:
<root>
<item id="Root" type="folder">
<content>
<name>Root</name>
</content>
<item id="One" type="file">
<content>
<name>First File in the Tree</name>
</content>
<item id="Two" type="file">
<content>
<name>Second File in the Tree</name>
</content>
</item>
</item>
</item>
</root>
Or even more concise, holding the same information:
<folder id="Root" name="Root">
<file id="One" name="First File in the Tree">
<file id="Two" name="Second File in the Tree" />
</file>
</folder>
I am assigned to web part of some project.There are two parts in this project,
window and web.In window part,User can create their own customized template
like visual studio IDE,you can addform and other controls.And then,we save this template
with data in xml file.My duty isto read from this xml file and create webform.
For web part,just showing information that createdfrom window part.
our xml file format is like below.For web part,we developed in c#.net with asp.net mvc.
<Object type="System.Windows.Forms.Form">
<Object type="System.Windows.Forms.Label">
<Property name="Name">lblCity</Property>
<Property name="Text">City</Property>
</Object>
<Object type="System.Windows.Forms.TextBox">
<Property name="Name">txtCity</Property>
<Property name="Text">England</Property>
</Object>
<Object type="System.Windows.Forms.Label">
<Property name="Name">lblNRIC</Property>
<Property name="Text">NRIC</Property>
</Object>
<Object type="System.Windows.Forms.TextBox">
<Property name="Name">txtNRIC</Property>
<Property name="Text">ABC01234</Property>
</Object>
<Object type="System.Windows.Forms.RadioButton">
<Property name="Name">RadioButton1</Property>
<Property name="Text">OptionA</Property>
</Object>
<Object type="System.Windows.Forms.CheckBox">
<Property name="Name">CheckBox1</Property>
<Property name="Text">Yes</Property>
</Object>
<Object type="System.Windows.Forms.CheckBox">
<Property name="Name">CheckBox2</Property>
<Property name="Text">No</Property>
</Object>
<SampleDataSet>
<SampleTable>
<TableName>Sample1</TableName>
<ProductName>ABC</ProductName>
<Price>100</Price>
<Qty>10</Qty>
<Amount>1000</Amount>
</SampleTable>
<SampleTable>
<TableName>Sample2</TableName>
<ProductName>DEF</ProductName>
<Price>200</Price>
<Qty>20</Qty>
<Amount>4000</Amount>
</SampleTable>
<SampleTable>
<TableName>Sample3</TableName>
<ProductName>GHK</ProductName>
<Price>300</Price>
<Qty>30</Qty>
<Amount>9000</Amount>
</SampleTable>
</SampleDataSet>
</Object>
We know it should not be create web form like window part,but,we really need it.
So,how i solve my problem?can i use xml serilization?
please give me right ways with some examples.
Regards
Han
You could use XSLT to transform this XML to XHTML. Also, you could inherit your own XMLBasedFormResult from MVC ActionResult class and generate form HTML at ExecuteResult method using C# (e.g. with LinqToXML).
Well, don't you think you will really end up duplicating what visual studio does..?
I would suggest you use something like WPF, which can be shown in the browser as well as in the Windows app. I am telling from experience this idea of parsing xml and generating UI is not very good..it is almost like writing a jsp/asp engine.
Also i noticed that the xml you have there has no formatting information, location on screen, color, style, font etc..
How do you intend on populating text boxes, dropdown lists, menus etc..?
As mace said XSLT is a good solution.
This is the xls stylesheet:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Template for <Object type="System.Windows.Forms.Form -->
<xsl:template match="*[#type = 'System.Windows.Forms.Form']">
<!-- Here's the html's form tag -->
<form>
<fieldset>
<xsl:apply-templates />
</fieldset>
</form>
</xsl:template>
<!-- Template for <Object type="System.Windows.Forms.Label -->
<xsl:template match="*[#type = 'System.Windows.Forms.Label']">
<!-- Here's the html's label tag -->
<label><xsl:value-of select="." /></label>
</xsl:template>
<!-- Template for <Object type="System.Windows.Forms.TextBox -->
<xsl:template match="*[#type = 'System.Windows.Forms.TextBox']">
<!-- Create the html's input tag -->
<xsl:element name="input">
<!-- And set the attributes -->
<xsl:attribute name="name">
<xsl:value-of select="./Property[#name ='Name']" />
</xsl:attribute>
<xsl:attribute name="type">text</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="./Property[#name ='Text']" />
</xsl:attribute>
</xsl:element>
</xsl:template>
<!-- Add here templates for RadioButton, Checkbox ... -->
</xsl:stylesheet>
You can read this Tutorial to get basic skills of xls.
You can run this xsl transformation now in C#:
//load the Xml doc
XPathDocument myXPathDoc = new XPathDocument(sXmlPath) ;
XslTransform myXslTrans = new XslTransform() ;
//load the Xsl
myXslTrans.Load(sXslPath) ;
//create the output stream
XmlTextWriter myWriter = new XmlTextWriter
("result.html", null);
//do the actual transform of Xml
myXslTrans.Transform(myXPathDoc,null, myWriter);
myWriter.Close() ;
You have to modify that for your scenario. Look at the MSDN for information about the XslTransform-class etc.
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