XSLT:Preceeding元素,可能不是兄弟,但不跨越特定标记

时间:2011-05-19 23:51:53

标签: xslt

我正在尝试执行一些文本规范化来替换一些收缩。以下是一些示例输入:

<?xml version="1.0"?>
<transcript>
  <p id="p1">
    <s id="s1"><w>Here</w><w>'s</w> <w>an</w> <w>example</w>, <w>let</w><w>'s</w> <w>consider</w> <w>it</w></s>
    <s id="s2"><w>Here</w> <w>'s</w> <w>an</w> <w>example</w>, <w>let</w><w>'s</w> <w>consider</w> <w>it</w></s>
    <s id="s3"><foo><w>Here</w></foo><bar><w>'s</w></bar> <w>an</w> <w>example</w>, <foo><w>let</w></foo><w>'s</w> <w>consider</w> <w>it</w></s>
    <s id="s4"><w>Here</w><bar><baz><w>'s</w></baz></bar> <w>an</w> <w>example</w>, <baz><bar><w>let</w></bar><w>'s</w></baz> <w>consider</w> <w>it</w></s>
    <s id="s5"><w>Look</w> <w>here</w></s>
    <s id="s6"><w>'s</w> <w>another</w> <w>example</w></s>
  </p>
</transcript>

在这个例子中,我想用“hers is”替换“here's”,用“let us”替换“let's”。因此,我想要的输出是,

<?xml version="1.0"?>
<transcript>
  <p id="p1">
    <s id="s1"><w>Here</w> <w>is</w> <w>an</w> <w>example</w>, <w>let</w> <w>us</w> <w>consider</w> <w>it</w></s>
    <s id="s2"><w>Here</w>  <w>is</w> <w>an</w> <w>example</w>, <w>let</w>  <w>us</w> <w>consider</w> <w>it</w></s>
    <s id="s3"><foo><w>Here</w></foo> <bar><w>is</w></bar> <w>an</w> <w>example</w>, <foo><w>let</w></foo> <w>us</w> <w>consider</w> <w>it</w></s>
    <s id="s4"><w>Here</w> <bar><baz><w>is</w></baz></bar> <w>an</w> <w>example</w>, <baz><bar><w>let</w></bar> <w>us</w></baz> <w>consider</w> <w>it</w></s>
    <s id="s5"><w>Look</w> <w>here</w></s>
    <s id="s6"><w>'s</w> <w>another</w> <w>example</w></s>
  </p>
</transcript>

我能够将可以处理s1s2的一些代码(可能没有任何接近优雅或最佳的代码)组合在一起,但我没有看到我可以将它概括为有用的东西。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml"/>

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

<xsl:template match="w[translate(text(),'S','s')=&quot;'s&quot;][preceding-sibling::*[1]/self::w[translate(text(),'HERE','here')='here']]">
  <xsl:text> </xsl:text>
  <xsl:copy><xsl:copy-of select="@*"/>is</xsl:copy>
</xsl:template>

<xsl:template match="w[translate(text(),'S','s')=&quot;'s&quot;][preceding-sibling::*[1]/self::w[translate(text(),'LET','let')='let']]">
  <xsl:text> </xsl:text>
  <xsl:copy><xsl:copy-of select="@*"/>us</xsl:copy>
</xsl:template>

</xsl:stylesheet>

一些细节:

  • 假设单词全部包含在<w>标签中,并且感兴趣的“单词”是连续的(尽管不一定是兄弟姐妹)

  • 任意标签可以包含单词和单词中的一个或两个。

  • 替换不应跨越句子<s>边界(如s5和s6所示) - 但如果这是不可能的,我不会哭。

  • 如果word和s之间已经存在空格,我仍然想要替换's。结果的确切间距(一个或两个空格)无关紧要。

  • 理想情况下,空格会被添加到包含单词和s的两个<w>标记的最近共同祖先。

感谢您提供任何指导!

1 个答案:

答案 0 :(得分:2)

此转换符合所有要求

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" exclude-result-prefixes="my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <my:AposS>'s</my:AposS>

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

 <xsl:template match=
  "w[. = document('')/*/my:AposS
   and
     not(generate-id()
        =
         generate-id(ancestor::s[1]/descendant::w[1])
         )
   and
     preceding::w[1] = 'Here'
    ]
  ">
  <w>is</w>
 </xsl:template>

 <xsl:template match=
  "w[. = document('')/*/my:AposS
   and
     not(generate-id()
        =
         generate-id(ancestor::s[1]/descendant::w[1])
         )
   and
     preceding::w[1] = 'let'
    ]
  ">
  <w>us</w>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<transcript>
    <p id="p1">
        <s id="s1">
            <w>Here</w>
            <w>'s</w>
            <w>an</w>
            <w>example</w>, 
            <w>let</w>
            <w>'s</w>
            <w>consider</w>
            <w>it</w>
        </s>
        <s id="s2">
            <w>Here</w>
            <w>'s</w>
            <w>an</w>
            <w>example</w>, 
            <w>let</w>
            <w>'s</w>
            <w>consider</w>
            <w>it</w>
        </s>
        <s id="s3">
            <foo>
                <w>Here</w>
            </foo>
            <bar>
                <w>'s</w>
            </bar>
            <w>an</w>
            <w>example</w>, 
            <foo>
                <w>let</w>
            </foo>
            <w>'s</w>
            <w>consider</w>
            <w>it</w>
        </s>
        <s id="s4">
            <w>Here</w>
            <bar>
                <baz>
                    <w>'s</w>
                </baz>
            </bar>
            <w>an</w>
            <w>example</w>, 
            <baz>
                <bar>
                    <w>let</w>
                </bar>
                <w>'s</w>
            </baz>
            <w>consider</w>
            <w>it</w>
        </s>
        <s id="s5">
            <w>Look</w>
            <w>here</w>
        </s>
        <s id="s6">
            <w>'s</w>
            <w>another</w>
            <w>example</w>
        </s>
    </p>
</transcript>

生成了想要的结果

<transcript>
   <p id="p1">
      <s id="s1">
         <w>Here</w>
         <w>is</w>
         <w>an</w>
         <w>example</w>, 
            <w>let</w>
         <w>us</w>
         <w>consider</w>
         <w>it</w>
      </s>
      <s id="s2">
         <w>Here</w>
         <w>is</w>
         <w>an</w>
         <w>example</w>, 
            <w>let</w>
         <w>us</w>
         <w>consider</w>
         <w>it</w>
      </s>
      <s id="s3">
         <foo>
            <w>Here</w>
         </foo>
         <bar>
            <w>is</w>
         </bar>
         <w>an</w>
         <w>example</w>, 
            <foo>
            <w>let</w>
         </foo>
         <w>us</w>
         <w>consider</w>
         <w>it</w>
      </s>
      <s id="s4">
         <w>Here</w>
         <bar>
            <baz>
               <w>is</w>
            </baz>
         </bar>
         <w>an</w>
         <w>example</w>, 
            <baz>
            <bar>
               <w>let</w>
            </bar>
            <w>us</w>
         </baz>
         <w>consider</w>
         <w>it</w>
      </s>
      <s id="s5">
         <w>Look</w>
         <w>here</w>
      </s>
      <s id="s6">
         <w>'s</w>
         <w>another</w>
         <w>example</w>
      </s>
   </p>
</transcript>