Given the following input xml file, i need to search for values, and replace them in the input xml
the search for values are in the xslt, each row must be replaced by its equivalent row.
<TABLE NAME="TEST">
<DATA RECORDS="78">
<catalog>
<book id="bk109">
<description>2ος Όροφος</description>
</book>
<book id="bk110">
<description>Microsoft's .NET initiative is explored in detail in this deep programmer's reference.</description>
</book>
<book id="bk111">
<description>An anthology of HORROR stories about roaches, centipedes, scorpions and other insects.</description>
</book>
<book id="bk112">
<description>2ος όροφος</description>
</book>
<book id="bk113">
<description>An anthology of horror stories about roaches, centipedes, scorpions and other insects.</description>
</book>
<book id="bk114">
<description>Microsoft's .NET initiative is explored in detail in this deep PROGRAMMER's reference.</description>
</book>
<book id="bk115">
<description>An anthology of HORROR stories about roaches, centipedes, scorpions and other insects.</description>
</book>
<book id="bk116">
<description>An anthology of horror stories about roaches, centipedes, scorpions and other insects. Beware, this must not be matched.</description>
</book>
<book id="bk114">
<description>Microsoft's .NET initiative is explored in detail in this deep PROGRAMMER's reference. Beware, this must not be matched.</description>
</book>
</catalog>
</DATA>
</TABLE>
and the following xslt:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:functx="http://www.functx.com"
exclude-result-prefixes="xs functx">
<xsl:param name="search-text" as="xs:string">2ος Όροφος
2ος όροφος</xsl:param>
<xsl:param name="replacement-text" as="xs:string">2ος όροφoς
2ος όροφoς</xsl:param>
<xsl:param name="search-terms" as="xs:string*" select="tokenize($search-text, '\r?\n')"/>
<xsl:param name="search-terms-is" as="xs:string*" select="for $term in $search-terms return concat('^', lower-case(functx:escape-for-regex($term)), '$')"/>
<xsl:param name="replace-terms" as="xs:string*" select="tokenize($replacement-text, '\r?\n')"/>
<xsl:include href="http://www.xsltfunctions.com/xsl/functx-1.0-nodoc-2007-01.xsl"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="description[some $search-term in $search-terms-is satisfies matches(., $search-term, 'i')]">
<xsl:copy>
<xsl:variable name="matched-term" as="xs:string" select="$search-terms-is[matches(current(), ., 'i')]"/>
<xsl:variable name="replacement" as="xs:string" select="$replace-terms[index-of($search-terms-is, $matched-term)]"/>
<xsl:value-of
select="$replacement"/>
</xsl:copy>
</xsl:template>
</xsl:transform>
i get the errors.
How could the above be altered, so as to keep all the code the xslt has, but avoid the following error?
<?xml version="1.0" encoding="UTF-8"?><TABLE NAME="TEST">
<DATA RECORDS="78">
<catalog>
<book id="bk109">
Error on line 30
XTTE0570: A sequence of more than one item is not allowed as the value of variable
$matched-term ("^2ος όροφος$", "^2ος όροφος$")
at xsl:apply-templates (#23)
processing /TABLE/DATA[1]/catalog[1]/book[1]/description[1]
at xsl:apply-templates (#23)
processing /TABLE/DATA[1]/catalog[1]/book[1]
at xsl:apply-templates (#23)
processing /TABLE/DATA[1]/catalog[1]
at xsl:apply-templates (#23)
processing /TABLE/DATA[1]
in built-in template rule
live here: http://xsltransform.net/pNvs5wd
Also i would appreciate an xslt, where the search and replace values could be loaded in external files. ie search.txt, replace.txt
The posted code assumes any search term is entered once and is the converted by the XSLT to lower case in <xsl:param name="search-terms-is" as="xs:string*" select="for $term in $search-terms return concat('^', lower-case(functx:escape-for-regex($term)), '$')"/>
. Furthermore the matching of input data with the search terms in some $search-term in $search-terms-is satisfies matches(., $search-term, 'i')
is done using the i
flag to use case-insensitive matching. Your two terms 2ος Όροφος
and 2ος όροφος
differ only in the case of characters so they both result in a match of the input data. As the variable storing the match is type as xs:string
expecting only a single match you get that error.
To fix that you should either make sure your search terms contain a certain term only once or you need to remove the use of lower-case
and the i
flag.
As for using text files with the search and replacement list, XSLT 2 and later supports the XPath 2 and later unparsed-text(file-uri, optional-encoding)
function you can use as in
<xsl:param name="searchFile" as="xs:string">search-terms.txt</xsl:param>
<xsl:param name="search-text" as="xs:string" select="unparsed-text($searchFile)"/>
to load the terms from a text file.