XSLT: анализировать строку текста с дочерними узлами - PullRequest
0 голосов
/ 28 сентября 2018

Я пытаюсь использовать анализ-строку для элементов, которые могут содержать дочерние узлы.Вот фрагмент исходного файла: <year> 1975 music </year> <year> 1985<genre>rock</genre>music </year> <year> 2005 music </year>

И вот что я хотел бы получить:

    <year>
        70's music
    </year>
    <year>
        80's<genre>rock</genre> music
    </year>

Следующий код правильно соответствует 3 случаям, но я пропускаючто-то, чтобы скопировать как текст, так и возможные дочерние узлы под элементом year:

<xsl:template match="year">
    <xsl:variable name="item" select="."/>
    <xsl:analyze-string select="." regex="19(\d)\d">
        <xsl:matching-substring>
            <xsl:variable name="decade">
                <xsl:value-of select="concat(regex-group(1),'0''s')"/>
            </xsl:variable>
            <year>
                <xsl:value-of select="concat($decade,regex-group(2))"/>
                <genre><xsl:value-of select="$item/genre"/>
                </genre>

            </year>
        </xsl:matching-substring>
        <xsl:non-matching-substring> </xsl:non-matching-substring>
    </xsl:analyze-string>
</xsl:template>

Вот что я получаю:

    <year>70's<genre/></year>
    <year>80's<genre>rock</genre></year>

Заранее спасибо за любую помощь!

1 Ответ

0 голосов
/ 28 сентября 2018

Кажется, что достаточно сопоставить текстовый дочерний элемент для шаблона года:

  <xsl:template match="year[not(matches(., $pattern))]"/>

  <xsl:template match="year/text()[matches(., $pattern)]">
      <xsl:value-of select="replace(., $pattern, '$10''s')"/>
  </xsl:template>

Это дает

<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:mode on-no-match="shallow-copy"/>

  <xsl:param name="pattern" as="xs:string">19(\d)\d</xsl:param>

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="year[not(matches(., $pattern))]"/>

  <xsl:template match="year/text()[matches(., $pattern)]">
      <xsl:value-of select="replace(., $pattern, '$10''s')"/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / gWmuiJV дает результат

<root>
       <year>
            70's music
        </year>
        <year>
            80's<genre>rock</genre>music
        </year>

</root>

Для решения, совместимого с XSLT 2, вам нужно прописать объявление xsl:mode, используемое в качестве шаблона преобразования идентификаторов, например для этого на http://xsltransform.hikmatu.com/jyH9rLQ.

...