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.
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>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:pi="urn:com.workday/picof">
I have the following map:
<xsl:variable name="tabsNames">
<entry><name>A</name><value>one</value></entry>
<entry><name>B</name><value>two</value></entry>
</xsl:variable>
I would like to iterate the map to get each key and value assigned to a variable:
<xsl:for-each select="$tabsNames/element()">
<xsl:variable name="tabName" select="./entry/name"/>
<xsl:variable name="tabValue" select="./entry/value"/>
</xsl:for-each>
How should the select look like in order to get name and value?
Well, a variable alone does nothing but given your variable with a temporary tree containing some entry elements if you want to process them with for-each and have the name and value in your variables inside of the for-each use e.g.
<xsl:for-each select="$tabsNames/entry">
<xsl:variable name="tabName" select="name"/>
<xsl:variable name="tabValue" select="value"/>
</xsl:for-each>
Given the namespaces you have shown in your edit of the question you have two choices, either you need to make sure your temporary elements in the variable do not end up in the default namespace xmlns="urn:schemas-microsoft-com:office:spreadsheet" you have on your stylesheet, you can do that with
<xsl:variable name="tabsNames" xmlns="">
<entry><name>A</name><value>one</value></entry>
<entry><name>B</name><value>two</value></entry>
</xsl:variable>
then my suggestion above remains valid, or you need to adjust your paths with e.g.
<xsl:for-each select="$tabsNames/ss:entry">
<xsl:variable name="tabName" select="ss:name"/>
<xsl:variable name="tabValue" select="ss:value"/>
</xsl:for-each>
or
<xsl:for-each select="$tabsNames/entry" xpath-default-namespace="urn:schemas-microsoft-com:office:spreadsheet">
<xsl:variable name="tabName" select="name"/>
<xsl:variable name="tabValue" select="value"/>
</xsl:for-each>
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
how can I display the text inside a for-each loop, in xslt, using each time a different css class? can I generate somehow the name of the css class based on some variable or something?? is it possible?
for example in the following code inside the foreach loop can I display the li with a different css class each time...such as in the first iteration li class="1"...second iteartion li class="2"...and obvious in css exists li.1{..}, li.2{...}
<xsl:output method="text" indent="no"/>
<xsl:variable name="newline">
<xsl:text>
</xsl:text>
</xsl:variable>
<xsl:template match="/">
<xsl:text>Collections of books</xsl:text>
<xsl:value-of select="$newline"/>
<xsl:variable name="index" select="0"/>
<xsl:for-each select="collection/book">
<xsl:sort select="category"/>
<xsl:variable name="lastCat" select="category"/>
<xsl:if test="not(preceding-sibling::book[category=$lastCat])">
<xsl:value-of select="$newline"/>
<xsl:value-of select="category"/>
<xsl:value-of select="$newline"/>
<xsl:value-of select="$newline"/>
</xsl:if>
<ul>
<li>
<xsl:value-of select="title"/>
<xsl:text> </xsl:text>
<xsl:value-of select="author"/>
<xsl:text> </xsl:text>
<xsl:value-of select="year"/>
<xsl:text> </xsl:text>
<xsl:value-of select="isbn"/>
</li>
</ul>
<xsl:value-of select="$newline"/>
</xsl:for-each>
</xsl:template>
You're XSLT is a little confusing as to whether you are outputting text or html. However, in answer to your immediate question you can easily add attributes to the exist li elements you are outputing in one of two ways.
Firstly, you can make use of the xsl:attribute statement, which should be added immediately following the li tag.
<li>
<xsl:attribute name="class">
<xsl:value-of select="position()" />
</xsl:attribute>
...
The better method though is to use 'attribute value templates' to specify attributes. (The curly brackets indicate an AVT to be evaluated in this case, as opposed to being a piece of text to be literally output)
<li class="{position()}">
...
In both cases the output will be similar to the following
<li class="1">...
<li class="2">...
In this example I am simply using the position() to demonstrate how you can set attributes, but you could easily use variables if required.
<li class="{$classname}">
I am using a third party asp.net control to pull and display the latest content from the database. The control pulls the title of the latest published content using a xsl file. My issue is the title(content piece) being too long. They place I used to display has no room for about 100 characters. I need to trim(not the white spaces) end part and may be limit it to a few words or some characters. It uses the xsl file -
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<xsl:for-each select="Collection/Content">
<tr>
<td>
<a>
<xsl:attribute name="href">
<xsl:choose>
<xsl:when test="Type ='Assets' or Type = 8 ">
javascript:void window.open('showcontent.aspx?id=<xsl:value-of select="ID"/>')
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="QuickLink"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:value-of select="Title"/>
</a>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
This part, <xsl:value-of select="Title"/> is where you the title is and I need to shorten it.. (putting ... in the end perhaps)
How can I do it? Can I get this done in the xsl file itself without using JQuery? Many thanks,
<xsl:choose>
<xsl:when test="string-length(Title) > 100">
<xsl:value-of select="substring(Title, 1, 97)" />...
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="Title" />
</xsl:otherwise>
</xsl:choose>
You can use the substring(text, startingIndex, length) XSLT function:
<xsl:value-of select="substring(Title, 1, 100)"/>
Note that substring index starts from 1, instead of the usual 0.
More at http://zvon.org/xxl/XSLTreference/Output/xpathFunctionIndex.html
Note also, that .NET does not implements XSLT 2.0, only XSLT 1.0 (hence the above reference: its the list of XSLT 1.0 functions).
Limit the 20 characters
If your code likes this
<xsl:value-of select="EmpBio" disable-output-escaping="yes"/>
Just change with new one written below
<xsl:value-of select="substring(BioData, 1, 20)" disable-output-escaping="yes"/>
Note that the quotation marks are removed from the element name BioData