Используйте xslt:analyze-string для добавления акронимов в HTML — теперь с синонимами

Я уже разместил вопрос о том, как добавить теги акронимов в текст HTML, и получил хорошее решение (см. -html">Используйте xslt:analyze-string для добавления сокращений в HTML ). Спасибо!

Теперь я добавил синонимы к своим аббревиатурам и адаптировал решение - работает нормально.

Мой единственный вопрос: полезно ли помещать инструкцию xsl:analyze-string для синонимов внутри части xsl:non-matching-substring первой строки xsl:analyze-string основного слова (имени)? Есть ли другие способы реализовать это?

Ниже мой источник и трансформация.

Спасибо за ваши подсказки! :-)

Суйду

исходный файл.xml:

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

        <acronym name="WWW">
            <synonym>www</synonym>
            <description>The World Wide Web</description>
        </acronym>

        <acronym name="HTML">
            <synonym>html</synonym>
            <description>The HyperText Markup Language</description>
        </acronym>

    </dictionary>

    <div>
        <p>In the <strong>www</strong> you can find a lot of <em>html</em> documents.</p> 
    </div>

</doc> 

преобразование.xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my"  exclude-result-prefixes="my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="/*">
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="text()" priority="0.1">
    <xsl:sequence select="my:insert-acronyms(., /*/dictionary/acronym)"/>
</xsl:template>

<xsl:function name="my:insert-acronyms" as="node()*">
    <xsl:param name="text" as="text()"/>
    <xsl:param name="acronyms" as="node()*"/>

    <xsl:sequence select=
         "if($acronyms)
            then my:replace-words($text, $acronyms/@name, $acronyms/synonym)
            else $text
         "/>
</xsl:function>

<xsl:function name="my:replace-words" as="node()*">
    <xsl:param name="text" as="text()" />
    <xsl:param name="names" as="node()*" />
    <xsl:param name="synonyms" as="node()*" />

    <xsl:analyze-string select="$text" 
         regex="{concat('(^|\W)(', string-join($names, '|'), ')(\W|$)')}">
         <xsl:matching-substring>
          <xsl:value-of select="regex-group(1)"/>
          <acronym title="{$names[. eq regex-group(2)]/../description}">
           <xsl:value-of select="regex-group(2)"/>
          </acronym>
          <xsl:value-of select="regex-group(3)"/>
         </xsl:matching-substring>
         <xsl:non-matching-substring>

            <xsl:analyze-string select="." 
                 regex="{concat('(^|\W)(', string-join($synonyms, '|'), ')(\W|$)')}">
                 <xsl:matching-substring>
                  <xsl:value-of select="regex-group(1)"/>
                  <acronym title="{$synonyms[. eq regex-group(2)]/../description}">
                   <xsl:value-of select="regex-group(2)"/>
                  </acronym>
                  <xsl:value-of select="regex-group(3)"/>
                 </xsl:matching-substring>
                 <xsl:non-matching-substring>
                    <xsl:value-of select="."/>
                 </xsl:non-matching-substring>
            </xsl:analyze-string>


         </xsl:non-matching-substring>
    </xsl:analyze-string>
</xsl:function>

<xsl:template match="dictionary"/>
</xsl:stylesheet>

person Suidu    schedule 15.12.2010    source источник


Ответы (1)


Вы снова все усложняете! ;-)

Отличное решение Dimitries можно легко настроить в соответствии с вашими потребностями, не вводя еще один xsl:analyze-string.

Все, что вам нужно сделать, это объединить @name и synonym при вызове my:replace-words:

my:replace-words($text, ($acronyms/@name|$acronyms/synonym))

Затем соответствующим образом настройте функцию my:replace-words, удалив параметр synonyms и используя xsl:value-of в xsl:non-matching-substring, как вы делали это раньше.

Замените текущую функцию my:insert-acronyms на:

  <xsl:function name="my:insert-acronyms" as="node()*">
    <xsl:param name="text" as="text()"/>
    <xsl:param name="acronyms" as="node()*"/>

    <xsl:sequence select="
      if($acronyms) then
        my:replace-words($text, ($acronyms/@name|$acronyms/synonym))
      else 
        $text"/>
  </xsl:function>

... и ваш текущий my:replace-words с:

  <xsl:function name="my:replace-words" as="node()*">
    <xsl:param name="text" as="text()" />
    <xsl:param name="names" as="node()*" />

    <xsl:analyze-string select="$text" 
      regex="{concat('(^|\W)(', string-join($names, '|'), ')(\W|$)')}">
      <xsl:matching-substring>
        <xsl:value-of select="regex-group(1)"/>
        <acronym title="{$names[. eq regex-group(2)]/../description}">
          <xsl:value-of select="regex-group(2)"/>
        </acronym>
        <xsl:value-of select="regex-group(3)"/>
      </xsl:matching-substring>
      <xsl:non-matching-substring>
        <xsl:value-of select="."/>
      </xsl:non-matching-substring>
    </xsl:analyze-string>
  </xsl:function>

Сделав это, следующий XML:

<?xml version="1.0" encoding="UTF-8"?>
<doc>
  <dictionary>
    <acronym name="WWW">
      <synonym>www</synonym>
      <description>The World Wide Web</description>
    </acronym>
    <acronym name="HTML">
      <synonym>html</synonym>
      <description>The HyperText Markup Language</description>
    </acronym>
    <acronym name="XSLT">
      <synonym>xslt</synonym>
      <description>Extensible Stylesheet Language Transformations</description>
    </acronym>
  </dictionary>
  <div>
    <p>In the <strong>www</strong> you can xslt find a lot of <em>html</em> documents.</p> 
  </div>
</doc> 

Возвращает следующий результат:

<div>
  <p>In the <strong>
      <acronym title="The World Wide Web">www</acronym>
    </strong> you can <acronym title="Extensible Stylesheet Language Transformations">xslt</acronym> find a lot of <em>
      <acronym title="The HyperText Markup Language">html</acronym>
    </em> documents.</p>
</div>
person Per T    schedule 15.12.2010