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>
我能够组合一些可以处理
s1
s2
代码(可能几乎没有优雅或最优的代码),但是我看不出可以将其概括为有用的代码
<?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(),\'LET\',\'let\')=\'let\']]\">
  <xsl:text> </xsl:text>
  <xsl:copy><xsl:copy-of select=\"@*\"/>us</xsl:copy>
</xsl:template>

</xsl:stylesheet>
一些细节: 假设所有单词都包裹在“ 5”标签中,并且感兴趣的“单词”是连续的(尽管不一定是兄弟姐妹) 任意标签可以包装单词和\的一个或另一个或两者。 替代词不应跨越句子“ 6”的边界(如s5和s6所示)-尽管如果这不可能,我也不会哭。 如果单词和\之间已经存在空格,我仍然想替换\。结果的确切间距(一个或两个空格)无关紧要。 理想情况下,将空格添加到包含单词和\的两个
<w>
标签中最接近的公共祖先。 感谢您的指导!     

解决方法

此转换满足所有要求:
<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>