Rectangle 27 2

http://xslttest.appspot.com/ ==> not given error.its working fine.

As others have already commented, the function fn:replace is a function added in XSLT 2.0 (actually, XPath 2.0, which is part of XSLT 2.0). Run your stylesheet with a 2.0 processor (like Saxon, Exselt or Altova) and you should be fine. How to configure it for your product depends on whether it supports using / plugging in a different processor.

Note: the namespace you use for fn is wrong. You do not need to specify that namespace (it's implicit), but if you do, use xmlns:fn="http://www.w3.org/2005/xpath-functions".

xml - Why is the Replace function is not working in xslt 2.0 - Stack O...

xml xslt-2.0
Rectangle 27 8

Replace is not valid in XSLT 1.0. You have "translate()", which might work for you, but replace() is XSLT 2, and not part of the MS .NET XML codebase. You can get it with some third party XML libraries though.

xml - XSLT Replace function not found - Stack Overflow

xml regex xslt xpath replace
Rectangle 27 8

Replace is not valid in XSLT 1.0. You have "translate()", which might work for you, but replace() is XSLT 2, and not part of the MS .NET XML codebase. You can get it with some third party XML libraries though.

xml - XSLT Replace function not found - Stack Overflow

xml regex xslt xpath replace
Rectangle 27 5

Using Saxon 9.4.06EE (evaluation copy) the result is:

<Test xmlns:fo="http://www.w3.org/1999/XSL/Format"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:fn="http://www.w3.org/2005/xpath-functions"
      xmlns:own="http://ownfunctions">
   <EarliestDate>2001-01-01</EarliestDate>
</Test>

Saxon-EE 9.4.0.6J from Saxonica
Java version 1.6.0_31
Using license serial number XXXXXXXX
Generating byte code...
Stylesheet compilation time: 2168 milliseconds
Processing file:/C:/Program%20Files/Java/jre6/bin/marrowtr.xml
Using parser com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser
Building tree for file:/C:/Program%20Files/Java/jre6/bin/marrowtr.xml using class net.sf.saxon.tree.tiny.TinyBuilder
Tree built in 10 milliseconds
Tree size: 27 nodes, 80 characters, 0 attributes
Execution time: 122ms
Memory used: 52169472
NamePool contents: 8 entries in 8 chains. 6 URIs

BTW, one can use just this to produce the same result

<xsl:value-of select="min(/*/*/Date/xs:date(.))"/>

The problem is in this line:

<xsl:value-of select="own:findEarliestDate-helper($items, $i - 1, $next)"/>

Because the return type of the function is xs:date, the above line isn't the last line in the execution sequence of the function. It produces a string (more precisely, a text node), and the XSLT processor needs to get this string and to convert it to an xs:date -- that means that the memory ocupied by the function isn't discarded and the call-stack continues to grow, until it overflows.

The solution is simple

Replace the above with:

<xsl:sequence select="own:findEarliestDate-helper($items, $i - 1, $next)"/>

This produces an xs:date and the XSLT processor now recognizes the function as tail recursive.

I tested the corrected code with 1000 events (on which the original code crashes) and the result is produced normally (and faster).

Saxon-EE 9.4.0.6J from Saxonica
Java version 1.6.0_31
Using license serial number XXXXXXXXXX
Generating byte code...
Stylesheet compilation time: 2002 milliseconds
Processing file:/C:/Program%20Files/Java/jre6/bin/marrowtr.xml
Using parser com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser
Building tree for file:/C:/Program%20Files/Java/jre6/bin/marrowtr.xml using class net.sf.saxon.tree.tiny.TinyBuilder
Tree built in 124 milliseconds
Tree size: 3032 nodes, 9800 characters, 0 attributes
Execution time: 364ms
Memory used: 55089048
NamePool contents: 8 entries in 8 chains. 6 URIs

Thanks for the fast reply (+1)! I tested the short version and it is definitely efficient enough (works great with 5000 Events). Although it would be nice to know why my function is not behaving as a tail-recursive one. It stucks at 150-200 Events, but this probably depends on the VM heap size. Could you please try with lots of Events? I could update the input, but it would be huge. Just say what you prefer. Thanks again.

@Ivo, You are welcome.

Do try to break the habit of using "xsl:value-of". Every time you write this, you should ask yourself whether xsl:sequence would be more appropriate. The xsl:value-of instruction creates a text node; in this example you are converting a date to a text node which is then converted back to a date.

Tail-recursive function in XSLT 2.0 is not working - Stack Overflow

xslt xslt-2.0 saxon
Rectangle 27 1

The translate function of XPath and XSLT 1.0 serves only to replace one Unicode character by another Unicode character; you can provide a list of input and replacement characters where then each character in the first list is then replaced by the one in the second list at the same position. But to replace complete works or phrases you need other tools.

You have not said or described whether you want to replace the complete attribute value, assuming that you can (with XSLT 2.0) simply do e.g.

<root>
  <foo bar="IANAL"/>
  <foo bar="WYSIWYG"/>
</root>
<root>
  <foo baz="I am not a lawyer"/>
  <foo baz="What you see is what you get"/>
</root>

If you want to do several replacements of substrings in one value or string then more effort is needed but with the replace function in XSLT/XPath 2.0 that is possible too.

Here is an example using a list of items and a recursive function replacing phrases:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="xs mf"
  version="2.0">

<xsl:key name="phrase" match="phrase" use="@input"/>

<xsl:function name="mf:replace-phrases" as="xs:string">
  <xsl:param name="phrases" as="element(phrase)*"/>
  <xsl:param name="text" as="xs:string"/>
  <xsl:choose>
    <xsl:when test="not($phrases)">
      <xsl:sequence select="$text"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:sequence select="mf:replace-phrases($phrases[position() gt 1], replace($text, $phrases[1]/@input, $phrases[1]/@output))"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:function>

<xsl:param name="phrases">
  <phrases>
    <phrase input="IANAL" output="I am not a lawyer"/>
    <phrase input="WYSIWYG" output="What you see is what you get"/>
  </phrases>
</xsl:param>

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* , node()"/>
  </xsl:copy>
</xsl:template>


<xsl:template match="foo/@bar">
  <xsl:attribute name="baz" select="mf:replace-phrases($phrases/phrases/phrase, .)"/>
</xsl:template>

</xsl:stylesheet>
<root>
  <foo bar="He said: 'IANAL'. I responded: 'WYSIWYG', and he smiled."/>
</root>
<root>
  <foo baz="He said: 'I am not a lawyer'. I responded: 'What you see is what you get', and he smiled."/>
</root>

Thanks, I'm using v2, but the created attribute is always empty (in every element, even though I've only got one test phrase defined). Does the test work for you?

sry, my mistake. I wrapped a 'choose' clause arround the thing to stop non relevant values being replaced with empty strings

xml - XSL list of words to replace, most easy defintion - Stack Overfl...

xml xslt xslt-2.0
Rectangle 27 0

http://xslttest.appspot.com/ ==> not given error.its working fine.

As others have already commented, the function fn:replace is a function added in XSLT 2.0 (actually, XPath 2.0, which is part of XSLT 2.0). Run your stylesheet with a 2.0 processor (like Saxon, Exselt or Altova) and you should be fine. How to configure it for your product depends on whether it supports using / plugging in a different processor.

Note: the namespace you use for fn is wrong. You do not need to specify that namespace (it's implicit), but if you do, use xmlns:fn="http://www.w3.org/2005/xpath-functions".

xml - Why is the Replace function is not working in xslt 2.0 - Stack O...

xml xslt-2.0
Rectangle 27 0

XPath 2.0 has a replace function that you can use with any XSLT 2.0 processor like Saxon 9 or AltovaXML tools or Gestalt. You seem to try to use the function with an XSLT 1.0 processor, that is not going to work. In case you are restricted to an XSLT 1.0 processor you will need to implement the replacement with a named recursive template or with the help of an extension.

However note that even with XSLT 2.0 your attempt to use replace seems wrong as you will produce a text node with a 'p' tag markup while I assume you want to create a 'p' element node in the result. So even with XSLT 2.0 using analyze-string instead of replace is more likely to get you the result you want.

Thx, mentioning XSLT 2.0 pushed me in the right direction. By bumping the version attribute of <xsl:stylesheet>; to 2.0 and using <xsl:value-of select="replace(description, '\n', 'p/')" disable-output-escaping="yes" />; I get the job done. Maybe analyze-string is cleaner but this gets the job done :)

Did you do anything other than just bump the version to 2.0?

can you tell me how to bumping version attribute of <xsl:stylesheet> to 2.0?

xml - Using XPath function fn:replace from XSLT - Stack Overflow

xml xslt xpath
Rectangle 27 0

With XSLT 2.0 you can also use the replace() function, which accepts a regex pattern as the second parameter and an optional 4th parameter for regex flags.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" />
    <xsl:template match="path">
        <xsl:sequence select="replace(., '^/en','')"/>
    </xsl:template>
</xsl:stylesheet>

xml - How to replace string in XSLT? - Stack Overflow

xml xslt
Rectangle 27 0

Replace is not valid in XSLT 1.0. You have "translate()", which might work for you, but replace() is XSLT 2, and not part of the MS .NET XML codebase. You can get it with some third party XML libraries though.

xml - XSLT Replace function not found - Stack Overflow

xml regex xslt xpath replace
Rectangle 27 0

Do the "replace" normalization using an XSLT transformation, then use the XPath 2.0 deep-equal() function (perhaps within the same transformation) to do the comparison with reference results. This enables proper XML comparison semantics, e.g. ignoring insignificant whitespace, or arbitrary distinctions such as single-versus-double quotes.

Suggestion on approach to compare XMLs (instead of using regex with Ja...

java regex xml xml-parsing compare
Rectangle 27 0

That was great code Rohit; it definitely helped send me in the right direction. I was having a hard time getting the XSLT 2.0 code working in my LibreOffice installation, so I converted the code to use XSLT 1.0 (named templates instead of functions calls, and an extension to be able to pass a node into the recursive function). In case someone needs it, my code is below. Note that it is not general purpose code - you will need to replace my fields with your own.

This particular example exports a spreadsheet into a valid .plist file that is recognized by XCode. It has been tested with LibreOffice 3.5 running on Vista.

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
    xmlns:xt="http://www.jclark.com/xt"
    extension-element-prefixes="xt"
    xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
    xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
    exclude-result-prefixes="office table text">

    <!--xsl:output method = "xml" indent = "yes" encoding = "UTF-8" omit-xml-declaration = "no"/-->
    <xsl:output method = "xml" indent = "yes" encoding = "UTF-8" omit-xml-declaration = "no" doctype-system = "http://www.apple.com/DTDs/PropertyList-1.0.dtd" doctype-public = "-//Apple//DTD PLIST 1.0//EN" />

    <xsl:template name="getColumnValue">
        <xsl:param name="tableRow"/>
        <xsl:param name="colIndex"/>
        <xsl:param name="currentIndex"/>
        <xsl:choose>
            <xsl:when test="$currentIndex &lt; $colIndex">
                <xsl:variable name="repeatColumns" select="xt:node-set($tableRow)/table:table-cell[$currentIndex]/@table:number-columns-repeated"/>
                <xsl:choose>
                    <xsl:when test="$repeatColumns">
                        <xsl:choose>
                            <xsl:when test="$currentIndex + $repeatColumns - 1 &gt;= $colIndex">
                                <xsl:value-of select="xt:node-set($tableRow)/table:table-cell[$currentIndex]"/>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:variable name = "recursiveResult">
                                    <xsl:call-template name="getColumnValue">
                                        <xsl:with-param name="tableRow" select="$tableRow"/>
                                        <xsl:with-param name="colIndex" select="$colIndex - $repeatColumns + 1"/>
                                        <xsl:with-param name="currentIndex" select="$currentIndex + 1"/>
                                    </xsl:call-template>
                                </xsl:variable>
                                <xsl:value-of select="$recursiveResult"/>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:variable name = "recursiveResult">
                            <xsl:call-template name="getColumnValue">
                                <xsl:with-param name="tableRow" select="$tableRow"/>
                                <xsl:with-param name="colIndex" select="$colIndex"/>
                                <xsl:with-param name="currentIndex" select="$currentIndex + 1"/>
                            </xsl:call-template>
                        </xsl:variable>
                        <xsl:value-of select="$recursiveResult"/>

                    </xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="xt:node-set($tableRow)/table:table-cell[$colIndex]"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <!-- By setting the PropertyValue "URL" in the properties used in storeToURL(), -->
    <!-- we can pass a single parameter to this stylesheet.                         -->
    <!-- Caveat: If we use the "URL" property in the stylesheet and call in OOo     -->
    <!-- from the menu "File" > "Export...", OOo assigns a target URL. And that     -->
    <!-- might not be what we want.                                                 -->
    <xsl:param name="targetURL"/>

    <xsl:variable name="exportDate">
        <xsl:choose>
            <xsl:when test="string-length(substring-before($targetURL,';'))=10">
                <xsl:value-of select="substring-before($targetURL,';')"/>
            </xsl:when>
            <xsl:when test="string-length($targetURL)=10">
                <xsl:value-of select="$targetURL"/>
            </xsl:when>
        </xsl:choose>
    </xsl:variable>

    <xsl:variable name="exportUser">
        <xsl:if test="string-length(substring-after($targetURL,';'))>0">
            <xsl:value-of select="substring-after($targetURL,';')"/>
        </xsl:if>
    </xsl:variable>

    <xsl:template match="/">
        <plist version="1.0">
            <dict>
                <key>Animations</key>
                <array>
                    <!-- Process all tables -->
                    <xsl:apply-templates select="//table:table"/>
                </array>
            </dict>
        </plist>
    </xsl:template>


    <xsl:template match="table:table">
        <!-- Process all table-rows after the column labels in table-row 1 -->
        <xsl:for-each select="table:table-row">
            <xsl:if test="position()>1">
                <dict>
                    <key>character</key>
                    <string>
                        <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="1"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template>
                    </string>

                    <key>animation</key>
                    <string>
                        <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="2"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template>
                    </string>

                    <key>cycle</key>
                    <xsl:variable name="cycleTmp">
                        <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="3"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template>
                    </xsl:variable>
                    <xsl:if test="$cycleTmp > 0">
                        <true/>
                    </xsl:if>
                    <xsl:if test="$cycleTmp = 0">
                        <false/>
                    </xsl:if>

                    <key>frames</key>
                    <integer>
                        <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="4"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template>
                    </integer>

                    <key>randomSpeedPercent</key>
                    <integer>
                        <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="5"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template>
                    </integer>

                    <key>spriteNameRoot</key>
                    <string>
                        <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="6"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template>
                    </string>

                    <key>spriteSheetName</key>
                    <string>
                        <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="7"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template>
                    </string>

                    <key>anchorX</key>
                    <integer>
                        <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="11"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template>
                    </integer>

                    <key>anchorY</key>
                    <integer>
                        <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="12"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template>
                    </integer>

                </dict>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

export - OpenOffice bug while exporting from Calc using xslt filters -...

xslt export openoffice-calc
Rectangle 27 0

With XSLT 2.0 you can also use the replace() function, which accepts a regex pattern as the second parameter and an optional 4th parameter for regex flags.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" />
    <xsl:template match="path">
        <xsl:sequence select="replace(., '^/en','')"/>
    </xsl:template>
</xsl:stylesheet>

xml - How to replace string in XSLT? - Stack Overflow

xml xslt