Найти и заменить отдельные тексты внутри одного и того же узла text () более одного раза - PullRequest
0 голосов
/ 04 октября 2019

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

Здесь сценарии должны исключать элемент '

'. Хорошо работает, когда текст «найти» встречается только один раз в текстовом узле, если он встречается более одного раза, тогда пропускается процесс замены (см. Сначала). Пожалуйста, предложите.

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>

Ответы [ 2 ]

1 голос
/ 04 октября 2019

Я продолжаю думать, что вы можете использовать функцию 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

0 голосов
/ 04 октября 2019

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