Arhn - архитектура программирования

Найти и заменить определенные тексты в одном и том же узле text () более одного раза

Пожалуйста, предложите найти замену необходимого текста в одном узле text (), иногда поиск-замена текста повторяется более одного раза.

Здесь скрипты должны исключать элемент «‹p›». Работает нормально, когда текст «найти» встречается только один раз в текстовом узле, если он встречается более одного раза, то процесс замены пропускается (см. Сначала ‹p1>). Пожалуйста, предложите.

XML:

<article>
<p1>The text 1111, 2222, 3333 and 4444 are some values, 1111 another occurance.</p1>
<p1>The text 1111, 2222, 3333 and 4444 are some values</p1>
<p>The text 1111, 2222, 3333 and 4444 are some values</p>
<p1>The text aaaaa, bbbbb, ccccc and ddddd are another set of values</p1>
<p1>The text <i>aaaaa</i>, <b>bbbbb</b>  and <c>ccccc</c> are in different form</p1>
</article>

XSLT 2.0:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy>
</xsl:template>

<xsl:template match="*/text()">
    <xsl:call-template name="tempFindReplace">
        <xsl:with-param name="pText1" select="."/>
    </xsl:call-template>
</xsl:template>

<xsl:template name="tempFindReplace">
    <xsl:param name="pText1"/>
    <xsl:if test="string-length($pText1) > 0">
    <xsl:choose>
        <xsl:when test="ancestor::p1">
            <xsl:choose>
                <xsl:when test="contains($pText1, '1111')">
                    <xsl:value-of select="substring-before($pText1,'1111')"/><xsl:text>Alpha1</xsl:text>
                    <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '1111')"/></xsl:call-template></xsl:when>
                <xsl:when test="contains($pText1, '2222')">
                    <xsl:value-of select="substring-before($pText1,'2222')"/><xsl:text>Alpha2</xsl:text>
                    <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '2222')"/></xsl:call-template></xsl:when>
                <xsl:when test="contains($pText1, '3333')">
                    <xsl:value-of select="substring-before($pText1,'3333')"/><xsl:text>Alpha3</xsl:text>
                    <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '3333')"/></xsl:call-template></xsl:when>
                <xsl:when test="contains($pText1, '4444')">
                    <xsl:value-of select="substring-before($pText1,'4444')"/><xsl:text>Alpha4</xsl:text>
                    <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '4444')"/></xsl:call-template></xsl:when>

                <xsl:when test="contains($pText1, 'aaaaa')">
                    <xsl:value-of select="substring-before($pText1,'aaaaa')"/><xsl:text>Beta1</xsl:text>
                    <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'aaaaa')"/></xsl:call-template></xsl:when>
                <xsl:when test="contains($pText1, 'bbbbb')">
                    <xsl:value-of select="substring-before($pText1,'bbbbb')"/><xsl:text>Beta2</xsl:text>
                    <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'bbbbb')"/></xsl:call-template></xsl:when>
                <xsl:when test="contains($pText1, 'ccccc')">
                    <xsl:value-of select="substring-before($pText1,'ccccc')"/><xsl:text>Beta3</xsl:text>
                    <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'ccccc')"/></xsl:call-template></xsl:when>
                <xsl:when test="contains($pText1, 'ddddd')">
                    <xsl:value-of select="substring-before($pText1,'ddddd')"/><xsl:text>Beta4</xsl:text>
                    <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'ddddd')"/></xsl:call-template></xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="substring($pText1,1,1)"/>
                    <xsl:call-template name="tempFindReplace">
                        <xsl:with-param name="pText1" select="substring($pText1, 2)"/>
                    </xsl:call-template>
                </xsl:otherwise>
            </xsl:choose>
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="."/>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:if> 
</xsl:template>
</xsl:stylesheet>

Требуемый результат:

<article>
<p1>The text Alpha1, Alpha2, Alpha3 and Alpha4 are some values, Alpha1 another occurance.</p1><!-- Alpha1 only replacing, but other texts also required change, I assume here failing because of 1111 appearing twice-->
<p1>The text Alpha1, Alpha2, Alpha3 and Alpha4 are some values</p1>
<p>The text 1111, 2222, 3333 and 4444 are some values</p>
<p1>The text Beta1, Beta2, Beta3 and Beta4 are another set of values</p1>
<p1>The text <i>Beta1</i>, <b>Beta2</b>  and <c>Beta3</c> are in different form</p1>
</article>
04.10.2019

  • Если у вас есть доступ к XSLT 2, почему бы вам не использовать его replace функцию? Вам нужно будет вызывать его несколько раз для различных строк, которые вы хотите заменить, но вам определенно не нужен именованный шаблон, вызываемый рекурсивно. Что касается исключения содержимого элемента p, хорошо писать шаблон только для match="p1/text()" или для *[not(self::p)]/text(). 04.10.2019
  • Спасибо за предложение, здесь нужно исключить только 'p', могут быть ‹p2›, ‹p3› и т.д., необходимые для изменения, а для использования обычной функции replace () существует около 1000 текстов поиска-замены. Так что replace (replace, '', ''), '', '') неудобно делать 1000 замененных замен. 04.10.2019

Ответы:


1

Я продолжаю думать, что вы можете многократно использовать функцию replace, например, в XSLT 3 с xsl:iterate:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:param name="replacements" as="array(xs:string)*"
    select="['1111', 'Alpha1'], ['2222', 'Alpha2'], ['3333', 'Alpha3'], ['4444', 'Alpha4'], 
            ['aaaaa', 'Beta1'], ['bbbbb', 'Beta2'], ['ccccc', 'Beta3'], ['ddddd', 'Beta4'] "/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="article/*[not(self::p)]//text()">
      <xsl:iterate select="$replacements">
          <xsl:param name="text" select="."/>
          <xsl:on-completion>
              <xsl:value-of select="$text"/>
          </xsl:on-completion>
          <xsl:next-iteration>
              <xsl:with-param name="text" select="replace($text, .(1), .(2))"/>
          </xsl:next-iteration>
      </xsl:iterate>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bwdwrL

04.10.2019
  • Спасибо за предложение ‹xsl: iterate› плюс один, если я использую xlt3, то я подумал об использовании ‹xsl: value-of select =. = ›Replace ('1111', 'Alpha1') =› replace ('2222', 'Alpha2') / ›код, предложенный вами, сэр, в более ранних ответах. Но я использую xslt2. Здесь мне потребовалось, как избежать повторного вызова функции для получения результата. 05.10.2019

  • 2

    XSLT 2:

    дважды вызвал шаблон, и получил результат.

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy>
    </xsl:template>
    
    <xsl:template match="*[ancestor-or-self::*[matches(name(), '^(p1|p2|p3)$')]]/text()">
        <xsl:variable name="var1">
        <xsl:call-template name="tempFindReplace">
            <xsl:with-param name="pText1" select="."/>
        </xsl:call-template>
        </xsl:variable>
        <xsl:call-template name="tempFindReplace">
            <xsl:with-param name="pText1" select="$var1"/>
        </xsl:call-template>
    </xsl:template>
    
    <xsl:template name="tempFindReplace">
        <xsl:param name="pText1"/>
        <xsl:if test="string-length($pText1) > 0">
                <xsl:choose>
                    <xsl:when test="contains($pText1, '1111')">
                        <xsl:value-of select="substring-before($pText1,'1111')"/><xsl:text>Alpha1</xsl:text>
                        <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '1111')"/></xsl:call-template></xsl:when>
                    <xsl:when test="contains($pText1, '2222')">
                        <xsl:value-of select="substring-before($pText1,'2222')"/><xsl:text>Alpha2</xsl:text>
                        <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '2222')"/></xsl:call-template></xsl:when>
                    <xsl:when test="contains($pText1, '3333')">
                        <xsl:value-of select="substring-before($pText1,'3333')"/><xsl:text>Alpha3</xsl:text>
                        <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '3333')"/></xsl:call-template></xsl:when>
                    <xsl:when test="contains($pText1, '4444')">
                        <xsl:value-of select="substring-before($pText1,'4444')"/><xsl:text>Alpha4</xsl:text>
                        <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '4444')"/></xsl:call-template></xsl:when>
    
                    <xsl:when test="contains($pText1, 'aaaaa')">
                        <xsl:value-of select="substring-before($pText1,'aaaaa')"/><xsl:text>Beta1</xsl:text>
                        <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'aaaaa')"/></xsl:call-template></xsl:when>
                    <xsl:when test="contains($pText1, 'bbbbb')">
                        <xsl:value-of select="substring-before($pText1,'bbbbb')"/><xsl:text>Beta2</xsl:text>
                        <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'bbbbb')"/></xsl:call-template></xsl:when>
                    <xsl:when test="contains($pText1, 'ccccc')">
                        <xsl:value-of select="substring-before($pText1,'ccccc')"/><xsl:text>Beta3</xsl:text>
                        <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'ccccc')"/></xsl:call-template></xsl:when>
                    <xsl:when test="contains($pText1, 'ddddd')">
                        <xsl:value-of select="substring-before($pText1,'ddddd')"/><xsl:text>Beta4</xsl:text>
                        <xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'ddddd')"/></xsl:call-template></xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="substring($pText1,1,1)"/>
                        <xsl:call-template name="tempFindReplace">
                            <xsl:with-param name="pText1" select="substring($pText1, 2)"/>
                        </xsl:call-template>
                    </xsl:otherwise>
                </xsl:choose>
        </xsl:if> 
    </xsl:template>
    </xsl:stylesheet>
    
    04.10.2019
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..