Подстановка значений во многие элементы XML [XSLT 2.0] - PullRequest
1 голос
/ 01 сентября 2010

Этот вопрос является расширением этого . У меня есть много значений, как показано ниже:

<myStuff>
    <elem1>asdf</elem1>
    <elem2>foo bar</elem2>
    <elem3>foo bar foo</elem3>
    <elem4>foofoo</elem4>
</myStuff>

Я выполняю copy-of над MOST-элементами (select в copy-of очень специфично), а затем выполняю поиск и замену полученного XML, но я бы хотел объединить два В большинстве ситуаций, где я применил это, я заменил бы все, что говорит <xsl:value-of select="whatever"> на <xsl:apply-templates select="whatever"> и использовал бы следующий шаблон:

<xsl:template match="*">
    <xsl:variable name="rep1">
        <xsl:choose>
            <xsl:when test='matches(., ".*foo.*")'>
                <xsl:value-of select='replace(., "foo", "qwerty")' />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select='./text()' />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:variable name="rep2">
        <xsl:choose>
            <xsl:when test='matches(., ".*bar.*")'>
                <xsl:value-of select='replace($rep1, "bar", "myBar")' />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select='$rep1' />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:value-of select="$rep2" />
</xsl:template>

Я хотел бы использовать аналогичный шаблон для замены copy-of в моем коде (потому что я делаю те же замены, что и в других моих файлах, чтобы я мог использовать тот же шаблон), но я не уверен как это сделать.

Вывод будет выглядеть так:

<myOtherStuff>
    <elem1>asdf</elem1>
    <elem2>qwerty myBar</elem2>
    <elem3>qwerty myBar qwerty</elem3>
    <elem4>qwertyqwerty</elem4>
</myOtherStuff>

Вся помощь приветствуется и спасибо заранее!

Ответы [ 2 ]

2 голосов
/ 01 сентября 2010

При другом подходе эта таблица стилей:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes"/>
    <xsl:variable name="vReps" as="element()*">
        <rep target="foo" newval="qwerty"/>
        <rep target="bar" newval="myBar"/>
    </xsl:variable>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="text()">
        <xsl:analyze-string select="." 
         regex="{string-join($vReps/concat('(',@target,')'),'|')}">
            <xsl:matching-substring>
                <xsl:value-of select="$vReps[@target=current()]/@newval"/>
            </xsl:matching-substring>
            <xsl:non-matching-substring>
                <xsl:value-of select="."/>
            </xsl:non-matching-substring>
        </xsl:analyze-string>
    </xsl:template>
</xsl:stylesheet>

Вывод:

<myStuff>
    <elem1>asdf</elem1>
    <elem2>qwerty myBar</elem2>
    <elem3>qwerty myBar qwerty</elem3>
    <elem4>qwertyqwerty</elem4>
</myStuff>

Также этот ввод (из комментариев):

<myStuff>
    <elem>asdfooasdf</elem>
</myStuff>

Вывод:

<myStuff>
    <elem>asdqwertyasdf</elem>
</myStuff>

Примечание : Этот союз RegExp выполняет замену сразу.Это может отличаться от последовательных fn:replace вызовов: предположим, что эта замена нацеливается на «A» -> «B» и «B» -> «C» в этой строке «AB», замена объединения должна выводить «BC» и последовательно вызывать выход »CC ".

Примечание 2 : Что касается порядка соответствия, обратите внимание, что объединение RegExp следует своим собственным правилам (см. specs , более конкретно If two alternatives within the supplied $pattern both match at the same position in the $input string, then the match that is chosen is the first.) ипоследовательно fn:replace вызовы следуют в строго определенном пользователем порядке.

1 голос
/ 01 сентября 2010

Это преобразование :

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:my="my:my" >
 <xsl:output omit-xml-declaration="yes"/>

  <xsl:variable name="vReps" as="element()*">
   <rep target="foo" newval="qwerty"/>
   <rep target="bar" newval="myBar"/>
  </xsl:variable>

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

    <xsl:template match="text()">
      <xsl:sequence select="my:myMultiRep(., $vReps)"/>
    </xsl:template>

    <xsl:function name="my:myMultiRep" as="xs:string">
      <xsl:param name="pText" as="xs:string"/>
      <xsl:param name="pReps" as="element()*"/>

      <xsl:sequence select=
       "if(not($pReps))
         then $pText
         else my:myMultiRep(replace($pText, $pReps[1]/@target, $pReps[1]/@newval),
                            subsequence($pReps, 2)
                           )
       "/>
    </xsl:function>
</xsl:stylesheet>

при применении к предоставленному XML-документу :

<myStuff>
    <elem1>asdf</elem1>
    <elem2>foo bar</elem2>
    <elem3>foo bar foo</elem3>
    <elem4>foofoo</elem4>
</myStuff>

создает искомое, правильный результат :

<myStuff>
    <elem1>asdf</elem1>
    <elem2>qwerty myBar</elem2>
    <elem3>qwerty myBar qwerty</elem3>
    <elem4>qwertyqwerty</elem4>
</myStuff>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...