how to remove hyphen from string +xslt - xslt

how to remove hyphen from string like "19650512-0065" to "196505120065"
using this template : passing theID =
<xsl:template name="unformatLFPartyID">
<xsl:param name="theID" select="." />
<xsl:variable name="idSuffix" select="string-length($theID) - 3" />
<xsl:choose>
<xsl:when test="contains($theID,'-')">
<xsl:value-of select="substring($theID,0,$idSuffix)" />
<xsl:value-of select="substring($theID, $idSuffix)" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$theID" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>

Try replacing the xsl:variable and entire xsl:choose with:
<xsl:value-of select="translate($theID,'-','')"/>

Related

How can I split a string in xslt?

I want to split a string at the double quotation. Input string is as follow,
<S>Test Example "{test1}" is "{equal}" "{test2}"</S>
The xslt code that I'm using is,
<xsl:template name="SplitString">
<xsl:param name="text" select="''" />
<xsl:variable name="tag" select="substring-before(substring-after($text, '"'), '"')" />
<xsl:variable name="Remainder" select="substring-after($text, '"')" />
<xsl:choose>
<xsl:when test="$tag != ''">
<xsl:element name = "NP">
<xsl:value-of select = "$tag"/>
</xsl:element>
<!--recursive loop -->
<xsl:call-template name="SplitString">
<xsl:with-param name="text" select="$Remainder" />
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
The output that I'm getting is as follow,
<NP>{test}</NP>
<NP>is</NP>
<NP>{equal}</NP>
<NP> </NP>
<NP>{test2}</NP>
How can avoid the creation of empty element?
the desired output would be,
<NP>{test}</NP>
<NP>is</NP>
<NP>{equal}</NP>
<NP>{test2}</NP>
Just add a condition:
<xsl:if test="normalize-space($tag)">
<xsl:element name = "NP">
<xsl:value-of select = "$tag"/>
</xsl:element>
</xsl:if>

xslt case change transformation is removing the <br/ > tag from xml

I am doing a upper case to first character content in the xml data using the delimiters (space and hyphen) and am able to get the output correctly however this template is removing the break line tag in the table td area of xml. The output should be an xml.
eg:<text>
<table>
<tbody>
<tr>
<td>test<br />testing<br />tested</td>
</tr>
I see the code transforming as continous line without break tag in the output as below:I need to see the same br tag in xml output as in input xml however by capitalizing first letter of the word.
<text>
<table>
<tbody>
<tr>
<td>Testtestingtested</td>
</tr>
I am expecting to preserve and display the same break line tag to be in output xml even after the xslt tranformation so that the output will look correct instead of continous line
I am using the below xslt transformation:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
xmlns:n1="urn:hl7-org:v3" xmlns:n2="urn:hl7-org:sdtc">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match='n1:ClinicalDocument/n1:component/n1:structuredBody/n1:component/n1:section/n1:text/n1:table/n1:tbody/n1:tr'>
<xsl:copy>
<xsl:apply-templates select='n1:td'/>
</xsl:copy>
</xsl:template>
<xsl:template match="n1:td">
<xsl:copy>
<xsl:if test="./#ID">
<xsl:attribute name="ID" xml:space="default">
<xsl:value-of select="./#ID"/>
</xsl:attribute>
</xsl:if>
<xsl:call-template name="capitalize">
<xsl:with-param name="text" select="string(.)"/>
</xsl:call-template>
</xsl:copy>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template name="capitalize">
<xsl:param name="text" />
<xsl:param name="delimiter" select = "' '"/>
​
<xsl:variable name="upper-case" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="lower-case" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="word" select="substring-before(concat($text, $delimiter), $delimiter)" />
<xsl:choose>
<xsl:when test="$delimiter=' '">
<!-- tokenize word by 2nd delimiter -->
<xsl:call-template name="capitalize">
<xsl:with-param name="text" select="$word"/>
<xsl:with-param name="delimiter" select="'-'"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<!-- capitalize word -->
<xsl:value-of select="translate(substring($word, 1, 1), $lower-case, $upper-case) " />
<xsl:value-of select="translate(substring($word, 2), $upper-case, $lower-case)" />
</xsl:otherwise>
</xsl:choose>
<xsl:if test="contains($text, $delimiter)">
<xsl:value-of select="$delimiter"/>
<!-- recursive call -->
<xsl:call-template name="capitalize">
<xsl:with-param name="text" select="substring-after($text, $delimiter)" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Can anyone check and answer?
UPDATE: Both XSLT 1.0 and 2.0 solutions
All solutions preserve your line breaks and also work if you have inline markup of the text content.
First I make the lc and uc parameters global for more minified templates:
<xsl:param name="lc" select="'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ'"/>
<xsl:param name="uc" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'"/>
XSLT 1.0 or 2.0: You need to rewrite your first template to this regardless of the following XSLT solutions:
<xsl:template match="n1:td">
<xsl:copy>
<xsl:if test="./#ID">
<xsl:attribute name="ID" xml:space="default">
<xsl:value-of select="./#ID"/>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="node()" />
</xsl:copy>
<xsl:text>
</xsl:text>
</xsl:template>
XSLT 1.0
With XSLT 1.0 you need to combine a match template with a name template.
Match template: n1:td//text()
With this match template it becomes precisely what you request, make initial letter uppercase, and make letters following space and - uppercase:
<xsl:template match="n1:td//text()" >
<xsl:param name="text" select="." />
<xsl:param name="currentTextBlock" select="ancestor::n1:td[1]" />
<xsl:param name="isFirstTextNode">
<xsl:choose>
<xsl:when test="preceding::text()[ancestor::n1:td[generate-id(.) = generate-id($currentTextBlock)]]">false</xsl:when>
<xsl:otherwise>true</xsl:otherwise>
</xsl:choose>
</xsl:param>
<xsl:choose>
<xsl:when test="$isFirstTextNode = 'true'">
<xsl:value-of select="translate(substring($text, 1, 1), $lc, $uc)" />
<xsl:call-template name="capitalize">
<xsl:with-param name="text" select="$text" />
<xsl:with-param name="remainingText" select="substring($text,2)" />
<xsl:with-param name="index" select="2" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="capitalize">
<xsl:with-param name="text" select="$text" />
<xsl:with-param name="remainingText" select="$text" />
<xsl:with-param name="index" select="1" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
If you also want initial letter for each text node to be uppercase without adding space or hyphen, you can use this:
<xsl:template match="n1:td//text()" >
<xsl:param name="text" select="." />
<xsl:value-of select="translate(substring($text, 1, 1), $lc, $uc)" />
<xsl:call-template name="capitalize">
<xsl:with-param name="text" select="$text" />
<xsl:with-param name="remainingText" select="substring($text,2)" />
<xsl:with-param name="index" select="2" />
</xsl:call-template>
</xsl:template>
Name template: capitalize
This name template is can be used "as is" with both of the above match templates.
<xsl:template name="capitalize">
<xsl:param name="text" select="''" />
<xsl:param name="remainingText" select="''" />
<xsl:param name="index" select="1" />
<xsl:if test="$remainingText != ''">
<xsl:variable name="currentChar" select="substring($remainingText, 1, 1)" />
<xsl:choose>
<xsl:when test="$index = 1">
<xsl:value-of select="translate($currentChar, $uc, $lc)" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="previousChar" select="substring($text, $index - 1, 1)" />
<xsl:choose>
<xsl:when test="$previousChar = ' ' or $previousChar = '-'">
<xsl:value-of select="translate($currentChar, $lc, $uc)" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="translate($currentChar, $uc, $lc)" />
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="capitalize">
<xsl:with-param name="text" select="$text" />
<xsl:with-param name="remainingText" select="substring($remainingText, 2)" />
<xsl:with-param name="index" select="$index + 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
XSLT 2.0 (same as before):
This solution does precisely what you request, make initial letter uppercase, and make letters following space and - uppercase:
<xsl:template match="n1:td//text()" >
<xsl:param name="text" select="." />
<xsl:param name="currentTextBlock" select="ancestor::n1:td[1]" />
<xsl:param name="isFirstTextNode">
<xsl:choose>
<xsl:when test="preceding::text()[ancestor::n1:td[generate-id(.) = generate-id($currentTextBlock)]]">false</xsl:when>
<xsl:otherwise>true</xsl:otherwise>
</xsl:choose>
</xsl:param>
<xsl:for-each select="tokenize(replace(replace($text,'(.)','$1\\n'),'\\n$',''),'\\n')">
<xsl:variable name="pos" select="position()" />
<xsl:variable name="char" select="." />
<xsl:choose>
<xsl:when test="$isFirstTextNode = 'true' and $pos = 1">
<xsl:value-of select="translate($char, $lc, $uc) " />
</xsl:when>
<xsl:when test="substring($text, $pos - 1, 1) = ' ' or substring($text, $pos - 1, 1) = '-'">
<xsl:value-of select="translate($char, $lc, $uc) " />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="translate($char, $uc, $lc)" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
If you also want initial letter for each text node to be uppercase without adding space or hyphen, you can use this:
<xsl:template match="n1:td//text()" >
<xsl:param name="text" select="." />
<xsl:param name="currentTextBlock" select="ancestor::n1:td[1]" />
<xsl:for-each select="tokenize(replace(replace($text,'(.)','$1\\n'),'\\n$',''),'\\n')">
<xsl:variable name="pos" select="position()" />
<xsl:variable name="char" select="." />
<xsl:choose>
<xsl:when test="$pos = 1">
<xsl:value-of select="translate($char, $lc, $uc) " />
</xsl:when>
<xsl:when test="substring($text, $pos - 1, 1) = ' ' or substring($text, $pos - 1, 1) = '-'">
<xsl:value-of select="translate($char, $lc, $uc) " />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="translate($char, $uc, $lc)" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
The problem is your call on string(.), which takes the string value of the element: this strips out all markup.
You should be doing a recursive descent using xsl:apply-templates at each level to apply template rules to child nodes, all the way down to the leaf text nodes, and then your template rule for text nodes should be doing the case conversion.
Except that your capitalize logic seems to be trying to do something smart (I'm not sure what) which means it might need to look at something larger than a single text node. You might need a different rule for the first text node and for subsequent text nodes: it's hard to be sure without seeing a spec.
Another approach to this kind of problem is to do multiple passes: the first pass replaces the <br/> elements with some textual marker, e.g. "§br§", in the next pass you process the text as a string, and then finally you convert the markers back to element nodes.
With XSLT 3.0 you could do the first pass using fn:serialize() and the final pass using fn:parse-xml-fragment(); the "textual marker" would then be the actual lexical markup "<br/>" as a string of five characters. (But take care not to capitalise it!)

XSL Using replace and matches to update values

I am trying to update an old form that uses a data model that has changed, so any reference to the old model I want to replace with the new. I currently use the function matches to tell if I should preform the replace on the current string and then use the replace function to replace the value with the new one, the problem is that the regex used in the matches does not work with the regex in the replace.
<xsl:template
match="//*[contains(#*:default,'instance(''document'')/')
mode="pass">
<xsl:variable
name="regex"
as="element()*">
<regex>instance('document')/doc_type/description</regex>
<regex>anotherRegex</regex>
</xsl:variable>
<xsl:variable
name="replacement"
as="element()*">
<replacement>xxf:get-request-parameter('documentDesc')</replacement>
<replacement>replacedRegex</replacement>
</xsl:variable>
<xsl:element name="{name()}">
<xsl:for-each select="#*">
<xsl:choose>
<xsl:when test="name() = ('xxf:default')">
<xsl:attribute name="xxf:default">
<xsl:analyze-string
regex="{concat('(',$regex[1],'|',$regex[2],')')}"
select=".">
<xsl:matching-substring>
<xsl:if test="matches(.,$regex[1])">
<xsl:value-of select="replace(.,$regex[1],$replacement[1])" />
</xsl:if>
<xsl:if test="matches(.,$regex[2])">
<xsl:value-of select="replace(.,$regex[2],$replacement[2])" />
</xsl:if>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="." />
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="{local-name()}"><xsl:value-of select="." /></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:element>
</xsl:template>
Current XML:
<xf:bind id="clinic-bind"
name="clinic"
xxf:default="instance('document')/doc_type/description"
type="xf:string"/>
What I want to turn it into:
<xf:bind id="clinic-bind"
name="clinic"
xxf:default="xxf:get-request-parameter('documentDesc')"
type="xf:string"/>
So the Problem was basicaally I had to escape the '()' characters in the regex variable.
So I ended up with
<regex>instance\('document'\)/doc_type/description</regex>
In the regex part.

How XSLT treats multiple nested element?

I want to convert some plain text with special marker into HTML formatted text.
For example,
This is the original value
Th<italic>is is a <under>com<bold>bina</bold>tion</under></italic> text.
The original value as actual value (just for reference)
Th<italic>is is a <under>com<bold>bina</bold>tion</under></italic> text.
HTML format I expect as a result
Th<i>is is a <u>com<b>bina</b>tion</u></i> text.
I tried with below template but it can not be parsed by XSLT parser.
<xsl:template name="decorateValue">
<xsl:param name="originalString" />
<xsl:variable name="preString" select="substring-before($originalString, '<')" />
<xsl:variable name="postString" select="substring-after($originalString, '<')" />
<xsl:value-of select="$preString" />
<xsl:variable name="tagName" select="substring-before($postString, '>')" />
<xsl:choose>
<xsl:when test="$tagName='bold'">
<xsl:element name="b">
</xsl:when>
<xsl:when test="$tagName='/bold'">
</xsl:element>
</xsl:when>
<xsl:when test="$tagName='italic'">
<xsl:element name="i">
</xsl:when>
<xsl:when test="$tagName='/italic'">
</xsl:element>
</xsl:when>
<xsl:when test="$tagName='under'">
<xsl:element name="u">
</xsl:when>
<xsl:when test="$tagName='/under'">
</xsl:element>
</xsl:when>
</xsl:choose>
<xsl:call-template name="decorateValue">
<xsl:with-param name="originalString"
select="substring-after($postString, '>')" />
</xsl:call-template>
</xsl:template>
any idea to solve this?
I would appreciate in advance.
If you can actually keep the original text, your life would be easier. Then you can transform
Th<italic>is is a <under>com<bold>bina</bold>tion</under></italic> text. easily into xHTML
<xsl:template match="italic">
<xsl:element name="i">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
You can't mix your tags in your example. You open an xsl:when and open an xsl:element and then close the xsl:when. That is not valid XML!
So if you want to go with the encoded string you need something like:
<xsl:template name="decorateValue">
<xsl:param name="originalString" />
<xsl:if test="$originalString!=''">
<xsl:variable name="preString" select="substring-before($originalString, '<')" />
<xsl:variable name="postString" select="substring-after($originalString, '<')" />
<xsl:variable name="endString" select="'magic happens here!'" />
<xsl:value-of select="$preString" />
<xsl:variable name="tagName" select="substring-before($postString, '>')" />
<xsl:variable name="restString" select="'magic happens here!'" />
<xsl:choose>
<xsl:when test="$tagName='bold'">
<xsl:element name="b">
<xsl:call-template name="decorateValue">
<xsl:with-param name="originalString"
select="$restString" />
</xsl:call-template>
</xsl:element>
</xsl:when>
<xsl:when test="$tagName='italic'">
<xsl:element name="i">
<xsl:call-template name="decorateValue">
<xsl:with-param name="originalString"
select="$restString" />
</xsl:call-template>
</xsl:element>
</xsl:when>
<xsl:when test="$tagName='under'">
<xsl:element name="u">
<xsl:call-template name="decorateValue">
<xsl:with-param name="originalString"
select="$restString" />
</xsl:call-template>
</xsl:element>
</xsl:when>
</xsl:choose>
<xsl:value-of select="$endString" />
</xsl:if>
</xsl:template>
You see 2 places where 'magic happens here'. This is where you need to apply the string-before-last and string-after-last patterns (which are a PITA in XSLT). The best explanation can be found in the XSLT Cookbook (and you want to have XSLT 2.0 at least.
Hope the pointers help. You might consider breaking the pattern into individual, so you don't fish for > alone, but the full tags. You still need to use the before-last / after-last functions.

Default Namespace Issue during translation using xsl

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="no" indent="yes" />
<xsl:strip-space elements="*" />
<!-- <xsl:template match="//edx:rule" xmlns:edx="http://www.cisco.com/BRL">
<xsl:apply-templates />
</xsl:template> -->
<xsl:template match="*">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates select="#* | node()" />
</xsl:element>
</xsl:template>
<xsl:template match="lhs" name="lhsTemplate">
<xsl:element name="lhs">
<xsl:choose>
<xsl:when test="incident != ''">
<xsl:for-each select="incident">
<xsl:element name="freeForm">
<xsl:element name="text">
<xsl:apply-templates select="." />
<!-- <xsl:call-template name = "incidentTemplate"/> -->
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:when>
<xsl:when test="evaluate != ''">
<xsl:for-each select="evaluate">
<xsl:element name="freeForm">
<xsl:element name="text">
<xsl:apply-templates select="." />
<!-- <xsl:call-template name = "evaluateTemplate"/> -->
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:when>
<xsl:when test="ruleReference != ''">
<xsl:value-of select="ruleReference" />
</xsl:when>
<xsl:otherwise>
<xsl:text> no elements encountered in lhs block</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:template>
<xsl:template match="rhs" name="rhsTemplate">
<xsl:element name="rhs">
<xsl:choose>
<xsl:when test="modify != ''">
<xsl:for-each select="modify">
<xsl:element name="freeForm">
<xsl:element name="text">
<xsl:apply-templates select="." />
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:when>
<xsl:when test="tryCatchBlock/try/callFunction != ''">
<xsl:for-each select="tryCatchBlock/try/callFunction">
<xsl:element name="freeForm">
<xsl:element name="text">
<xsl:apply-templates select="." />
<xsl:text>;</xsl:text>
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:text> no elements encountered in Try block</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:template>
<!-- FIELE VALUES TEMPLATE -->
<xsl:template match="fieldValues" name="fieldValuesTemplate">
<xsl:for-each select="fieldValue" >
<!-- <xsl:if test="field!=''">
<xsl:value-of select="field"/>
<xsl:text>=</xsl:text>
</xsl:if> -->
<xsl:choose>
<xsl:when test="value/literal !=''">
<xsl:value-of select="value/literal"/>
</xsl:when>
<xsl:when test="value/formula !=''">
<xsl:apply-templates select="value/formula"/>
</xsl:when>
<xsl:when test="value/callMethodOnBoundVariable != ''">
<xsl:apply-templates select="value/callMethodOnBoundVariable"/>
</xsl:when>
<xsl:when test="value/callApi !=''">
<xsl:apply-templates select="."/>
</xsl:when>
<xsl:when test="value/boundVariable !=''">
<xsl:value-of select="value/boundVariable"/>
</xsl:when>
<xsl:when test="value/enum != ''">
<xsl:value-of select="value/enum"/>
</xsl:when>
<xsl:when test="value/content != ''">
<xsl:value-of select="value/content"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>No values encountered inside field</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="position() != last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
<!-- INSERT LOGICAL TEMPLATE -->
<xsl:template match="insertLogical" name="insertLogicalTemplate">
<xsl:value-of select="factType"/>
<xsl:text> </xsl:text>
<xsl:value-of select="boundName"/>
<xsl:text> = new </xsl:text>
<xsl:value-of select="factType"/>
<xsl:text>(</xsl:text>
<xsl:if test="fieldValues!=''">
<xsl:apply-templates select="fieldValues"/>
</xsl:if>
<xsl:text>);</xsl:text>
<xsl:text>insertLogical</xsl:text>
<xsl:text>(</xsl:text>
<xsl:value-of select="boundName"/>
<xsl:text>);</xsl:text>
</xsl:template>
<!-- END OF THE INSERT LOGICAL TEMPLATE -->
<!-- ASSERT MODIFY TEMPLATE -->
<xsl:template match="modify" name="modifyTemplate">
<xsl:text>modify</xsl:text>
<xsl:text>( </xsl:text>
<xsl:value-of select="variable"/>
<xsl:text> ){ </xsl:text>
<xsl:if test="fieldValues!=''">
<xsl:apply-templates select="fieldValues"/>
</xsl:if>
<xsl:text> };</xsl:text>
</xsl:template>
<!-- END OF THE MODIFY TEMPLATE -->
<!-- RETRACT TEMPLATE -->
<xsl:template match="retract" name="retractTemplate">
<xsl:text>retract(</xsl:text>
<xsl:value-of select="."/>
<xsl:text>);</xsl:text>
</xsl:template>
<!-- END OF THE RETRACT TEMPLATE -->
<!-- start leftOperandTemplate -->
<xsl:template match="leftOperand" name="leftOperandTemplate">
<xsl:choose>
<xsl:when test="field/fieldName != ''">
<xsl:value-of select="field/fieldName" />
</xsl:when>
<xsl:when test="boundVariable/variableName != ''">
<xsl:value-of select="boundVariable/variableName" />
</xsl:when>
<xsl:when test="expression != ''">
<xsl:apply-templates select="expression" /> <!-- TO DO -->
</xsl:when>
<xsl:when test="literal != ''">
<xsl:value-of select="literal" />
</xsl:when>
<xsl:when test="value/content != ''">
<xsl:value-of select="value/content" />
</xsl:when>
<xsl:when test="callFunction != ''">
<xsl:apply-templates select="callFunction" />
</xsl:when>
<xsl:when test="formula != ''">
<xsl:apply-templates select="formula" />
</xsl:when>
<xsl:when test="callApi != ''">
<xsl:apply-templates select="callApi" />
</xsl:when>
<xsl:when test="callMethodOnBoundVariable != ''">
<xsl:apply-templates select="callMethodOnBoundVariable" />
</xsl:when>
<xsl:otherwise>
<xsl:text>No left operands found!</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- end leftOperandTemplate -->
<!-- start Right operand template -->
<xsl:template match="rightOperand" name="rightOperandTemplate">
<xsl:choose>
<xsl:when test="boundVariable/variableName != ''">
<xsl:value-of select="boundVariable/variableName" />
</xsl:when>
<xsl:when test="configurableVariable/variableName != ''">
<xsl:value-of select="configurableVariable/variableName" />
</xsl:when>
<xsl:when test="literal != ''">
<xsl:value-of select="literal" />
</xsl:when>
<xsl:when test="value/content != ''">
<xsl:value-of select="value/content" />
</xsl:when>
<xsl:when test="callFunction != ''">
<xsl:apply-templates select="callFunction" />
</xsl:when>
<xsl:when test="formula != ''">
<xsl:apply-templates select="formula" />
</xsl:when>
<xsl:when test="callApi != ''">
<xsl:apply-templates select="callApi" />
</xsl:when>
<xsl:when test="callMethodOnBoundVariable != ''">
<xsl:apply-templates select="callMethodOnBoundVariable" />
</xsl:when>
<xsl:when test="expression != ''">
<xsl:apply-templates select="expression" /> <!-- TO DO -->
</xsl:when>
<xsl:otherwise>
<xsl:text>No right operands found!</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- end Right operand template -->
<!-- start Comparison operator template -->
<xsl:template match=" operator | comparisonOperator" name="compareOperatorTemplate">
<xsl:choose>
<xsl:when test=".='gt'">
<xsl:value-of select="' > '"
disable-output-escaping="yes" />
</xsl:when>
<xsl:when test=". = 'lt'">
<xsl:value-of select="' < '"
disable-output-escaping="yes" />
</xsl:when>
<xsl:when test=".='eq'">
<xsl:value-of select="' == '" disable-output-escaping="yes" />
</xsl:when>
<xsl:when test=". = 'ne'">
<xsl:value-of select="' != '" disable-output-escaping="yes" />
</xsl:when>
<xsl:when test=". = 'lt or eq'">
<xsl:value-of select="' <= '"
disable-output-escaping="yes" />
</xsl:when>
<xsl:when test=". = 'gt or eq'">
<xsl:value-of select="' >= '"
disable-output-escaping="yes" />
</xsl:when>
<xsl:when test=". = 'matches'">
<xsl:value-of select="' matches '" />
</xsl:when>
<xsl:when test=". = 'not matches'">
<xsl:value-of select="' not matches '" />
</xsl:when>
<xsl:when test=". = 'contains'">
<xsl:value-of select="' contains '" />
</xsl:when>
<xsl:when test=". = 'not contains'">
<xsl:value-of select="' not contains '" />
</xsl:when>
<xsl:when test=". = 'memberOf'">
<xsl:value-of select="' memberOf '" />
</xsl:when>
<xsl:when test=". = 'not memberOf'">
<xsl:value-of select="' not memberOf '" />
</xsl:when>
<xsl:when test=". = 'sounds like'">
<xsl:value-of select="' sounds like '" />
</xsl:when>
<xsl:otherwise>
<xsl:text>No operator found</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- End Comparison operator template -->
<xsl:template match="evaluate" name="evaluateTemplate">
<xsl:text disable-output-escaping="yes">eval(</xsl:text>
<xsl:if test=". !=''">
<xsl:apply-templates select="leftOperand" />
<xsl:if test="comparisonOperator !=''">
<xsl:apply-templates select="comparisonOperator" />
</xsl:if>
<xsl:apply-templates select="rightOperand" />
</xsl:if>
<xsl:text>)</xsl:text>
</xsl:template>
<!-- END EVALUATE TEMPLATE -->
<!-- start CALL FUNCTION TEMPLATE -->
<xsl:template match="callFunction" name="callFunctionTemplate">
<xsl:if test=". !=''">
<xsl:if test="returnType!='' and returnTypeBoundName !='' ">
<xsl:value-of select="returnType" />
<xsl:text> </xsl:text>
<xsl:value-of select="returnTypeBoundName" />
<xsl:text>=</xsl:text>
</xsl:if>
<xsl:if test="functionName!=''">
<xsl:value-of select="functionName" />
<xsl:text>(</xsl:text>
<!-- <xsl:apply-templates select="args"/> -->
<xsl:call-template name="argsTemplate" />
</xsl:if>
<xsl:text>)</xsl:text>
</xsl:if>
</xsl:template>
<!-- END OF THE CALL FUNCTION TEMPLATE -->
<!-- START ARGS TEMPLATE -->
<xsl:template match="args" name="argsTemplate">
<xsl:if test="args/arg != ''">
<xsl:for-each select="args/arg">
<xsl:choose>
<xsl:when test="callMethodOnBoundVariable != ''">
<xsl:apply-templates select="callMethodOnBoundVariable" />
</xsl:when>
<xsl:when test="callApi != ''">
<xsl:apply-templates select="callApi" />
</xsl:when>
<xsl:when test="value != ''">
<xsl:value-of select="value/content" />
</xsl:when>
<xsl:when test="literal != ''">
<xsl:value-of select="." />
</xsl:when>
<xsl:when test="boundVariable != ''">
<xsl:value-of select="boundVariable/variableName" />
</xsl:when>
<xsl:otherwise>
<xsl:text>No Args</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="position() != last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:if>
</xsl:template>
<!-- END OF THE ARGS TEMPLATE -->
<!-- START of the Call Method on Bound Variable function -->
<xsl:template match="callMethodOnBoundVariable" name="callMethodOnBoundVariableTemplate">
<xsl:value-of select="boundVariableName" />
<xsl:text>.</xsl:text>
<xsl:value-of select="methodName" />
<xsl:text>(</xsl:text>
<!-- <xsl:value-of select="params/param/boundVariable" /> -->
<xsl:call-template name="paramsTemplate" />
<xsl:text>)</xsl:text>
</xsl:template>
<!-- End of the Call Method on Bound Variable function -->
<!-- START CALL API TEMPLATE -->
<xsl:template match="callApi" name="callApiTemplate">
<!-- <xsl:if test="returnType != 'void'"> <xsl:value-of select="returnType
" /> <xsl:text> </xsl:text> </xsl:if> -->
<xsl:value-of select="boundVaribleName" />
<xsl:if test="boundVaribleName[.!='']">
<xsl:text>=</xsl:text>
</xsl:if>
<xsl:value-of select="serviceVariableName" />
<xsl:text>.</xsl:text>
<xsl:value-of select="methodName" />
<xsl:text>(</xsl:text>
<xsl:call-template name="paramsTemplate" />
<xsl:text>)</xsl:text>
</xsl:template>
<!-- END call API TEMPLATE -->
<!-- FORMULA TEMPLATE -->
<xsl:template match="formula" name="formulaTemplate">
<xsl:if test="'leftOperand'">
<xsl:call-template name="formulaWithoutPeranthesisTemplate" />
</xsl:if>
<xsl:if test="'peranthesis'">
<xsl:call-template name="formulaWithPeranthesisTemplate" />
</xsl:if>
</xsl:template>
<!-- END OF THE FORMULA TEMPLATE -->
<!-- start Formula without peranthesis template -->
<xsl:template match="formulaWithoutPeranthesis" name="formulaWithoutPeranthesisTemplate">
<xsl:if test="leftOperand">
<xsl:apply-templates select="leftOperand" />
</xsl:if>
<xsl:if test="arithmeticOperator">
<xsl:apply-templates select="arithmeticOperator" />
</xsl:if>
<xsl:if test="rightOperand">
<xsl:apply-templates select="rightOperand" />
</xsl:if>
</xsl:template>
<!-- End Formula without peranthesis template -->
<!-- start Formula withparenthesis template -->
<xsl:template match="formulaWithPeranthesis" name="formulaWithPeranthesisTemplate">
<xsl:if test="peranthesis != ''">
<xsl:text>(</xsl:text>
<xsl:if test="peranthesis/leftOperand !=''">
<xsl:apply-templates select="peranthesis/leftOperand" />
</xsl:if>
<xsl:if test="peranthesis/arithmeticOperator">
<xsl:apply-templates select="peranthesis/arithmeticOperator" />
</xsl:if>
<xsl:if test="peranthesis/rightOperand">
<xsl:apply-templates select="peranthesis/rightOperand" />
</xsl:if>
<xsl:text>)</xsl:text>
</xsl:if>
</xsl:template>
<!-- END Formula with parenthesis template -->
<!-- START ARITHMETIC OPERATOR -->
<xsl:template match="arithmeticOperator" name="arithmeticOperatorTemplate">
<xsl:choose>
<xsl:when test="'+'">
<xsl:value-of select=" . " />
</xsl:when>
<xsl:when test="'-'">
<xsl:value-of select=" . " />
</xsl:when>
<xsl:when test="'*'">
<xsl:value-of select=" . " />
</xsl:when>
<xsl:when test="'/'">
<xsl:value-of select=" . " />
</xsl:when>
<xsl:when test="'%'">
<xsl:value-of select=" . " />
</xsl:when>
<xsl:otherwise>
<xsl:text>Not a valid airthmetic operator</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- END ARITHMETIC OPERATOR -->
<!-- START OF THE PARAMS TEMPLATE -->
<xsl:template match="params" name="paramsTemplate">
<xsl:if test="params/param != ''">
<xsl:for-each select="params/param">
<xsl:choose>
<xsl:when test="callMethodOnBoundVariable != ''">
<xsl:apply-templates select="callMethodOnBoundVariable" />
</xsl:when>
<xsl:when test="formula != ''">
<xsl:apply-templates select="formula" />
</xsl:when>
<xsl:when test="callApi != ''">
<xsl:apply-templates select="callApi" />
</xsl:when>
<xsl:when test="value != ''">
<xsl:value-of select="value/content" />
</xsl:when>
<xsl:when test="literal != ''">
<xsl:text>"</xsl:text>
<xsl:value-of select="." />
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:when test="boundVariable != ''">
<xsl:value-of select="boundVariable" />
</xsl:when>
<xsl:when test="enum != ''">
<xsl:value-of select="enum" />
</xsl:when>
<xsl:otherwise>
<xsl:text>No Param</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="position() != last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:if>
</xsl:template>
<!-- END OF THE PARAMS TEMPLATE -->
<!--START COMPOSITE PATTERN TEMPLATE -->
<xsl:template match='compositePattern' name="compositePatternTemplate">
<xsl:if test="type != ''">
<xsl:value-of select="type" />
<xsl:text> </xsl:text>
</xsl:if>
<xsl:apply-templates select="patterns" />
</xsl:template>
<!-- END COMPOSITE PATTERN TEMPLATE -->
<xsl:template name="tagAndContentRemovalTemplate"
match=" nuggetVersion |nuggetId | ruleVersion | notes|ruleId | nuggetName | application | brlVersion | modelVersion | notes|declaration|preprocess " />
<xsl:template name="tagRemovalTemplate"
match=" ruleSection | blocks | block |actions | fieldRestriction | declaration | preprocess | tryCatchBlock |constraintList ">
<xsl:apply-templates />
<!-- set field and expression TBD -->
</xsl:template>
</xsl:stylesheet>
The Input file looks like below.
<?xml version="1.0" encoding="UTF-8"?>
<rule >
<name>IC-86</name>
<ruleId>1001</ruleId>
<ruleVersion>1.0</ruleVersion>
<nuggetId>1122</nuggetId>
<brlVersion>1.0</brlVersion>
<modelVersion>1.0</modelVersion>
<attributes>
<attribute>
<attributeName>agenda-group</attributeName>
<value>commonATSP</value>
</attribute>
</attributes>
<notes>Some text description about the rule, like what exactly it does...</notes>
<declaration />
<preprocess />
<ruleSection>
<blocks>
<block order="0">
<lhs>
<evaluate>
<leftOperand>
<boundVariable>
<variableName>$count</variableName>
<classType>Integer</classType>
<genericType>Number</genericType>
</boundVariable>
</leftOperand>
<comparisonOperator>gt</comparisonOperator>
<rightOperand>
<literal>10</literal>
</rightOperand>
</evaluate>
</lhs>
<rhs>
<modify>
<fieldValues>
<fieldValue>
<field>name</field>
<value>
<literal>$imageVersion</literal>
</value>
<nature>1</nature>
<type>String</type>
</fieldValue>
<fieldValue>
<field>value</field>
<value>
<callMethodOnBoundVariable>
<params>
<param>
<value>
<content>0</content>
<classType>int</classType>
<genericType>Numeric</genericType>
</value>
</param>
</params>
<boundVariableName>$attributes</boundVariableName>
<methodName>get</methodName>
<returnType>String</returnType>
</callMethodOnBoundVariable>
</value>
<nature>4</nature>
<type>String</type>
</fieldValue>
<fieldValue>
<field>type</field>
<value>
<literal>imageName</literal>
</value>
<nature>1</nature>
<type>String</type>
</fieldValue>
</fieldValues>
<variable>$attribute</variable>
</modify>
</rhs>
</block>
</blocks>
</ruleSection>
</rule>
I am facing an issue with my default namespace. I have a file with the root tag as below:
<rule xmlns="http://www.max.com/BRL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.max.com/BRL ../BRLV4.xsd ">
If I remove the namespaced <rule> as seen in the above input XML, then the translation works. Otherwise, it doesn't work. That is, if I try the translation without the default namespace then I am getting the required output as below. But I need the same output when I get the XML file with the default namespace on the root tag.
<?xml version="1.0" encoding="UTF-8"?>
<rule>
<name>IC-86</name>
<attributes>
<attribute>
<attributeName>agenda-group</attributeName>
<value>commonATSP</value>
</attribute>
</attributes>
<lhs>
<freeForm>
<text>eval($count > 10)</text>
</freeForm>
</lhs>
<rhs>
<freeForm>
<text>modify( $attribute ){ $imageVersion,$attributes.get(0),imageName };</text>
</freeForm>
</rhs>
</rule>
The default namespace in the XML document must be declared in the XSLT. For example, use the prefix 'brl'.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:brl="http://www.max.com/BRL">
Then use the brl prefix when referring to the tag names. For example,
<xsl:template match="brl:lhs" name="lhsTemplate">
...
<xsl:when test="brl:incident != ''">
<xsl:for-each select="brl:incident">
If the XML document may or may not have a namespace, see my article "Stay on the XPath: Tip 5: Handling XPath select expressions that fail to match documents with a default namespace" on IBM developerWorks.
Basically, you need your stylesheet to work whether all the elements are in no namespace, or in the BRL namespace. This is an odd requirement, and the ideal solution would be to tell your upstream data provider to be consistent about using the namespace.
But if you don't have that option, you have a few others.
1) Declare a prefix for the BRL namespace in your stylesheet, and use it to match elements in that namespace or in no namespace:
<xsl:stylesheet ... xmlns:BRL="http://www.max.com/BRL">
...
<xsl:template match="lhs | BRL:lhs">
...
2) Make all your matches and selects use local-name():
<xsl:template match="*[local-name()='lhs']">...
...
(Yuck!)
3) In XSLT 2.0, you can use the wildcard for namespaces:
<xsl:template match="*:lhs">
...
<xsl:when test="*:field/*:fieldName != ''">
But again, these three are all working around a problem in the source data. They are compensating for someone not using namespaces correctly, and thus enabling them to keep on doing the same. If the schema says the input document's elements should be in the "http://www.max.com/BRL" namespace, then you should assume that they are in that namespace (whether that's the default namespace is immaterial to you), so you should always be using a namespace prefix when matching or selecting those elements with XPath.