Recently, I was resolving an MSDN forum question that needs to split an input String to String destination nodes with maximum 80 length.
The problem was, how to generate N destination nodes with only one input node splitting the string in fixed length strings.
As BizTalk Maps uses XSLT 1.0, we can't use:
For example....
Then I use a recursive call to a XSLT template, to implement this. The objective is from a XML like this:
Get an XML like this:
The question is split the original Instructions element into N NTESegments elements, that have a maximum length of 80 chars:
My solution to solve this, was using a recursive call to an XSLT template. Here is the solution:
The problem was, how to generate N destination nodes with only one input node splitting the string in fixed length strings.
As BizTalk Maps uses XSLT 1.0, we can't use:
<xsl:for-each select="1 to 60">...</xsl:for-each>
For example....
Then I use a recursive call to a XSLT template, to implement this. The objective is from a XML like this:
<ns0:Root xmlns:ns0="http://BizTalkMassCopy.Instructions"> <Instructions>Instructions_0000000000000000000000000000000000000000000000000000000000000000ENDSECONDSEGMENT</Instructions> </ns0:Root>
Get an XML like this:
<ns0:Root xmlns:ns0="http://BizTalkMassCopy.NTESegment"> <NTESegment>Instructions_0000000000000000000000000000000000000000000000000000000000000000END</NTESegment> <NTESegment>SECONDSEGMENT</NTESegment> </ns0:Root>
The question is split the original Instructions element into N NTESegments elements, that have a maximum length of 80 chars:
- If Instructions length is less or equal than 80, then only one NTESegment at the output
- If Instructions length is greater than 80, generates NTESegments of 80 chars, to print all the content of Intructions.
My solution to solve this, was using a recursive call to an XSLT template. Here is the solution:
<?xml version="1.0" encoding="UTF-16"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var s0 userCSharp" version="1.0" xmlns:ns0="http://BizTalkMassCopy.NTESegment" xmlns:s0="http://BizTalkMassCopy.Instructions" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp"> <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" /> <xsl:template match="/"> <ns0:Root> <xsl:apply-templates select="/s0:Root" /> </ns0:Root> </xsl:template> <xsl:template name="recursive_loop" match="/s0:Root"> <xsl:param name="curposition">1</xsl:param> <xsl:variable name="var:length" select="userCSharp:StringSize(string(Instructions/text()))" /> <xsl:if test="not($curposition > $var:length)"> <xsl:if test="not($curposition + 80 > $var:length)"> <NTESegment> <xsl:variable name="var:current" select="userCSharp:StringSubstring(string(Instructions/text()), $curposition, $curposition + 80 - 1)" /> <xsl:value-of select="$var:current" /> </NTESegment> <xsl:call-template name="recursive_loop"> <xsl:with-param name="curposition"> <xsl:value-of select="$curposition + 80" /> </xsl:with-param> </xsl:call-template> </xsl:if> <xsl:if test="$curposition + 80 > $var:length"> <NTESegment> <xsl:variable name="var:current" select="userCSharp:StringSubstring(string(Instructions/text()), $curposition, $var:length)" /> <xsl:value-of select="$var:current" /> </NTESegment> </xsl:if> </xsl:if> </xsl:template> <msxsl:script language="C#" implements-prefix="userCSharp"> <![CDATA[ public int StringSize(string str) { if (str == null) { return 0; } return str.Length; } public string StringSubstring(string str, string left, string right) { string retval = ""; double dleft = 0; double dright = 0; if (str != null && IsNumeric(left, ref dleft) && IsNumeric(right, ref dright)) { int lt = (int)dleft; int rt = (int)dright; lt--; rt--; if (lt >= 0 && rt >= lt && lt < str.Length) { if (rt < str.Length) { retval = str.Substring(lt, rt-lt+1); } else { retval = str.Substring(lt, str.Length-lt); } } } return retval; } public bool IsNumeric(string val) { if (val == null) { return false; } double d = 0; return Double.TryParse(val, System.Globalization.NumberStyles.AllowThousands | System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out d); } public bool IsNumeric(string val, ref double d) { if (val == null) { return false; } return Double.TryParse(val, System.Globalization.NumberStyles.AllowThousands | System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out d); } ]]></msxsl:script> </xsl:stylesheet>
No comments:
Post a Comment