在XSLT中标记混合内容

时间:2016-04-01 10:44:16

标签: xml xslt xslt-2.0 tokenize

我有一个包含混合内容的元素<mixed>。是否可以使用XSLT(2.0)将所有“单词”(例如由模式\s+分隔)包裹在<mixed>标记内的<w>内,并在必要时降为内联元素?例如,给出以下输入:

<mixed>
  One morning, when <a>Gregor Samsa</a>
  woke from troubled dreams, he found
  himself transformed in his bed into
  a <b><c>horrible vermin</c></b>.
</mixed>

我想要以下输出:

<mixed>
  <w>One</w> <w>morning,</w> <w>when</w> <a><w>Gregor</w> <w>Samsa</w></a>
  <w>woke</w> <w>from</w> <w>troubled</w> <w>dreams,</w> <w>he</w> <w>found</w>
  <w>himself</w> <w>transformed</w> <w>in</w> <w>his</w> <w>bed</w> <w>into</w>
  <w>a</w> <b><c><w>horrible</w></c></b> <w><b><c>vermin</c></b>.</w>
</mixed>

Dimitre Novatchev在this related question的答案中提供了一个模板,该模板可以解决这个问题,但不满足以下要求:

  • 应该拆分在“单词”中终止的内联元素,以便单个<w>元素包含整个“单词”。否则会出现无效的XML,例如:

      <w>a</w> <w><b><c>horrible</w> <w>vermin</c></b>.</w>

    但是,此模板会在.之后分隔标点vermin并生成:

      <w>a</w> <b><c><w>horrible</w> <w>vermin</w></c></b> <w>.</(w>
    

    (编辑:当前3个答案中没有一个符合此要求。)

  • 不得丢弃拆分令牌。考虑在化学式的上下文中在<sub>标签中包装非系数数字的类似任务。例如,<reactants>2H2 + O2</reactants>变为<reactants>2H<sub>2</sub> + O<sub>2</sub></reactants>。使用tokenize函数无法实现这一点,因为它只是丢弃了分隔符。相反,我们可能不得不依靠analyze-string

如果不是XSLT,那么最好的方法是什么?

3 个答案:

答案 0 :(得分:1)

AFAICT,这将在您的示例中提供预期结果:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="text()[ancestor::mixed]">
    <xsl:analyze-string select="." regex="\s+">
        <xsl:matching-substring>
            <xsl:value-of select="." />
        </xsl:matching-substring>
        <xsl:non-matching-substring>
            <w>
                <xsl:value-of select="." />
            </w>
        </xsl:non-matching-substring>
    </xsl:analyze-string>
</xsl:template>

</xsl:stylesheet>

但是,我不明白你关于“内联元素终止于”字“”的观点。例如,当一个单词的一部分用斜体表示时,预期的结果是什么?

答案 1 :(得分:0)

如果您在"file:///var/mobile/Containers/Data/Application/EB2E7DCD-5B73-4B0B-9BC5-6758AF75C68C/Documents/FinalVideo-958.mov"上使用analyze-string

\S+

你得到了

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

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

    <xsl:template match="mixed//text()">
        <xsl:analyze-string select="." regex="\S+">
            <xsl:matching-substring>
                <w>
                    <xsl:value-of select="."/>
                </w>
            </xsl:matching-substring>
            <xsl:non-matching-substring>
                <xsl:value-of select="."/>
            </xsl:non-matching-substring>
        </xsl:analyze-string>
    </xsl:template>

</xsl:transform>

你真的想加入跟你内联元素中前面的<mixed> <w>One</w> <w>morning,</w> <w>when</w> <a><w>Gregor</w> <w>Samsa</w></a> <w>woke</w> <w>from</w> <w>troubled</w> <w>dreams,</w> <w>he</w> <w>found</w> <w>himself</w> <w>transformed</w> <w>in</w> <w>his</w> <w>bed</w> <w>into</w> <w>a</w> <b><c><w>horrible</w> <w>vermin</w></c></b><w>.</w> </mixed> 的尾随点吗?

答案 2 :(得分:0)

这个XSLT怎么样,它有一个额外的模板来处理紧跟一个只包含句号的文本节点的元素。

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" 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="text()">
  <xsl:for-each select="tokenize(., '[\s]')[.]">
   <w><xsl:sequence select="."/></w>
  </xsl:for-each>
 </xsl:template>

 <xsl:template match="text()[normalize-space() = '.']" />

 <xsl:template match="node()[following-sibling::node()[1][self::text()][normalize-space() = '.']]">
  <w>
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
     <xsl:text>.</xsl:text>
  </w>
 </xsl:template>
</xsl:stylesheet>