在2个元素之间设置样式文本所需的XSLT代码

时间:2012-12-10 14:36:26

标签: xslt xslt-1.0

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

我有一个类似于此的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的'markup'函数来标记搜索命中,并且我搜索字符串'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或命名模板来浏览文档的样式表,但我无法让它们工作。使用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>

3 个答案:

答案 0 :(得分: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>

解释

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

答案 1 :(得分: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>

答案 2 :(得分:0)

使用禁用输出转义的简单解决方案,以防止错误启动没有结尾的元素,并结束没有start元素的元素。

<?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>