поиск и замена XML-ошибки с использованием xslt2 - PullRequest
0 голосов
/ 26 апреля 2018

Учитывая следующий входной XML-файл, мне нужно найти значения и заменить их во входном XML

поиск значений осуществляется в xslt, каждая строка должна быть заменена своей эквивалентной строкой.

<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>

и следующий 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>

я получаю ошибки.

Как можно изменить вышеперечисленное, чтобы сохранить весь код xslt, но избежать следующей ошибки?

<?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

живи здесь: http://xsltransform.net/pNvs5wd

Также я был бы признателен за xslt, где значения поиска и замены могут быть загружены во внешние файлы. т.е. search.txt, replace.txt

1 Ответ

0 голосов
/ 26 апреля 2018

В размещенном коде предполагается, что любой поисковый термин вводится один раз и преобразуется XSLT в нижний регистр в <xsl:param name="search-terms-is" as="xs:string*" select="for $term in $search-terms return concat('^', lower-case(functx:escape-for-regex($term)), '$')"/>. Кроме того, сопоставление входных данных с поисковыми терминами в some $search-term in $search-terms-is satisfies matches(., $search-term, 'i') выполняется с использованием флага i для использования сопоставления без учета регистра. Ваши два термина 2ος Όροφος и 2ος όροφος отличаются только в случае символов, поэтому оба они приводят к совпадению входных данных. Поскольку переменная, хранящая совпадение, имеет тип xs:string, ожидая только одно совпадение, вы получите эту ошибку.

Чтобы исправить это, вы должны либо убедиться, что ваши поисковые термины содержат определенный термин только один раз, либо вам нужно удалить использование lower-case и флаг i.

Что касается использования текстовых файлов со списком поиска и замены, XSLT 2 и более поздние версии поддерживают функцию XPath 2 и более поздние unparsed-text(file-uri, optional-encoding), которую можно использовать, как в

<xsl:param name="searchFile" as="xs:string">search-terms.txt</xsl:param>
<xsl:param name="search-text" as="xs:string" select="unparsed-text($searchFile)"/>

для загрузки терминов из текстового файла.

...