3

我希望有人能帮我一把。这个问题已经困扰了我好几天了。我的问题的根源是我想在 2 个元素之间按文档顺序向所有节点添加标记。

我有一个与此类似的 XML 文档:

<Employees>
  <Employee>
    <Title>Mr.</Title>
    <FirstName>John</FirstName>
    <LastName>Doe</LastName>
</Employee>
  <Employee>
    <Title>Mr.</Title>
    <FirstName>Tom</FirstName>
    <LastName>Doe</LastName>
  </Employee>
</Employees>

当我使用 Oracle 的标记搜索命中的“标记”函数并搜索字符串“John Doe”时,我得到如下 XML 结果:

<Employees>
  <Employee>
    <Title>Mr.</Title>
    <FirstName><hitStart/>John</FirstName>
    <LastName>Doe<hitEnd/></LastName>
  </Employee>
  <Employee>
    <Title>Mr.</Title>
    <FirstName>Tom</FirstName>
    <LastName>Doe</LastName>
  </Employee>
</Employees>

我想将其转换为突出显示命中的 XHTML。例如,以下 XHTML 将是一个有用的结果:

<TABLE>
  <TR>
    <TD>Mr. <b style="color:red">John Doe</b></TD>
  <TR>
  <TR>
    <TD>Tom Doe</TD>
  </TR>
</TABLE>

我尝试编写使用应用模板或命名模板来浏览文档的样式表,但我无法让它们工作。使用 apply-templates 很棘手,因为我无法传递一个参数来说明节点是否在 hitStart 和 hitEnd 元素内。使用命名模板很棘手,因为我需要以不同方式处理文本和元素节点,而这在 XSLT 1.0 中无法做到。帮助将不胜感激。

谢谢,布赖恩

感谢所有帮助过的人!!!!你们太棒了!

这是我决定的:

<xsl:template match="/*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="node()[1]"/>
    </xsl:copy>
    <xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
<xsl:template match="text()[preceding::*[self::hitStart or self::hitEnd][1][self::hitStart]
and following::*[self::hitStart or self::hitEnd][1][self::hitEnd]]">
    <span style="color:red;font-style:italic;font-weight:bold"><xsl:value-of select="."/></span>
    <xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
<xsl:template match="hitStart|hitEnd">
    <xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
4

3 回答 3

3

这种转变

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

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

 <xsl:template match=
   "text()
      [preceding::*[self::hitStart or self::hitEnd][1][self::hitStart]
     and
       following::*[self::hitStart or self::hitEnd][1][self::hitEnd]
      ]">
    <xsl:value-of select="concat('*** ', ., ' ***')"/>
  </xsl:template>

 <xsl:template match="hitStart|hitEnd">
    <xsl:apply-templates select="following-sibling::node()[1]"/>
  </xsl:template>
 </xsl:stylesheet>

针对提供的 XML 文档应用时:

<Employees>
  <Employee>
    <Title>Mr.</Title>
    <FirstName><hitStart/>John</FirstName>
    <LastName>Doe<hitEnd/></LastName>
  </Employee>
  <Employee>
    <Title>Mr.</Title>
    <FirstName>Tom</FirstName>
    <LastName>Doe</LastName>
  </Employee>
</Employees>

突出显示hitStarthitEnd元素之间的每个文本节点——用三个星号包围它并产生想要的正确结果

<Employees>
   <Employee>
      <Title>Mr.</Title>
      <FirstName>*** John ***</FirstName>
      <LastName>*** Doe ***</LastName>
   </Employee>
   <Employee>
      <Title>Mr.</Title>
      <FirstName>Tom</FirstName>
      <LastName>Doe</LastName>
   </Employee>
</Employees>

说明

使用和覆盖“细粒度”身份规则。

于 2012-12-10T15:28:32.780 回答
1

这并不理想,但你可以做一些快速而肮脏的事情,比如......

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

    <xsl:output method="xml" encoding="utf-8" indent="no"/>

    <xsl:template match="/">
        <table>
            <xsl:apply-templates />
        </table>
    </xsl:template>

    <xsl:template match="FirstName[hitStart]">
        <span class="alert"><xsl:value-of select="."/>&#160;</span>
    </xsl:template>
    <xsl:template match="FirstName">
        <xsl:value-of select="."/>&#160;
    </xsl:template>
    <xsl:template match="LastName[hitEnd]">
        <span class="alert"><xsl:value-of select="."/></span>
    </xsl:template>
    <xsl:template match="LastName">
        <xsl:value-of select="."/>
    </xsl:template>
    <xsl:template match="Employees/Employee">
        <tr>
            <td>
                <xsl:apply-templates select="Title"/>
            </td>
            <td>
                <xsl:apply-templates select="FirstName | LastName"/>
            </td>
        </tr>
    </xsl:template>
</xsl:stylesheet>
于 2012-12-10T17:57:38.660 回答
0

简单的解决方案,使用禁用输出转义来防止错误开始没有结束的元素,以及结束没有开始元素的元素。

<?xml version="1.0"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xhtml" indent="yes"/>

    <xsl:template match="/Employees">
        <TABLE>
            <xsl:apply-templates select="Employee"/>
        </TABLE>
    </xsl:template>

    <xsl:template match="Employee">
        <TR>
            <TD><xsl:apply-templates/></TD>
        </TR>
    </xsl:template>

    <xsl:template match="hitStart">
        <xsl:value-of disable-output-escaping="yes" select="'&lt;b style=&quot;color:red&quot;&gt;'"/>
    </xsl:template>

    <xsl:template match="hitEnd">
        <xsl:value-of disable-output-escaping="yes" select="'&lt;/b&gt;'"/>
    </xsl:template>
</xsl:transform>
于 2012-12-10T22:10:46.970 回答