在两个元素之间设置文本样式所需的XSLT代码
我希望有人能帮我一把。这个问题困扰了我好几天了。我的问题的根源是我想在两个元素之间按文档顺序向所有节点添加标记 我有一个包含类似以下内容的XML的文档:在两个元素之间设置文本样式所需的XSLT代码,xslt,xslt-1.0,Xslt,Xslt 1.0,我希望有人能帮我一把。这个问题困扰了我好几天了。我的问题的根源是我想在两个元素之间按文档顺序向所有节点添加标记 我有一个包含类似以下内容的XML的文档: <Employees> <Employee> <Title>Mr.</Title> <FirstName>John</FirstName> <LastName>Doe</LastName> </Employee>
<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模板很棘手,因为我无法传递一个参数来说明节点是否在hitStart和hitEnd元素中。使用命名模板很棘手,因为我需要以不同的方式处理文本和元素节点,这在XSLT1.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>
此转换:
<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>
说明:
使用并覆盖“细粒度”标识规则。这并不理想,但您可以快速完成一些肮脏的操作,如
<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="."/> </span>
</xsl:template>
<xsl:template match="FirstName">
<xsl:value-of select="."/> 
</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>
一种简单的解决方案,使用“禁用输出转义”来防止错误在没有结束的情况下启动元素,在没有开始元素的情况下结束元素
<?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="'<b style="color:red">'"/>
</xsl:template>
<xsl:template match="hitEnd">
<xsl:value-of disable-output-escaping="yes" select="'</b>'"/>
</xsl:template>
</xsl:transform>
谢谢你,迪米特!这让我接近了。但是,如果和不是示例中的同级,则节点集不会拾取中间的节点。我想这就是答案,但我还有一点调整要做。@brianv,在这种情况下,使用轴:以下:
和前面::
再次感谢。这就是诀窍!最后一个问题是,我想为所有hitStart/hitEnd对运行逻辑。换句话说,我不知道会有多少个序数对。现在,我正在研究是否可以使用apply templates捕捉hitStart元素,然后在该模板匹配中,我尝试查看是否可以使用position()计算序号。到目前为止,没有运气。顺便说一句,我喜欢你在确定位置之前先用括号找到所有的hitStart和hitEnd元素。我不知道括号可以这样使用。谢谢!也许我可以使用position()来获取相对位置,例如:(//hitStart)[position()]/后面的同级::node()[count(.|(//hitEnd)[position()]/前面的同级::node())=count((//hitEnd)[position position position()]/前面的同级::node())。一旦我的开发环境再次开始响应,我将尝试一下:(没关系。除非我能找出逻辑来说明hitStart的位置应该与hitEnd的位置相匹配,否则这是行不通的。谢谢,Patrick。这对于示例来说似乎是可行的,但我应该提到我会有各种各样的用例。例如,我可能有AsdMaryQwerbeth。此外,元素可能有任何名称。没有定义的DTD。我想为hitStart和hitEnd元素之间的所有文本添加格式,而不为任何其他文本添加格式。我很好奇,为什么要使用span?我对HTML元素不太熟悉。谢谢!brianv,我用新的解决方案完全更改了答案。现在这样更好了吗?:)很好,Dimitre!!非常感谢。这就成功了。因为我的现实生活中的XML有属性,甚至在根节点上,我做了一些调整。以下是对我有效的方法:
很抱歉设置了格式。我不确定如何在这个网站上让它看起来更好。谢谢,Joepie!我根据上面Dimitre的建议找到了一个解决方案,所以我不确定这是否对我有效。我以前没有使用过禁用输出转义,所以这是一个有趣的想法。你是如何用Dimitre解决方案解决粗体开始标记和结束标记问题的?Joepie,我在我的问题中更新了上面的解决方案。我意识到我昨晚忘了,对不起。
<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="."/> </span>
</xsl:template>
<xsl:template match="FirstName">
<xsl:value-of select="."/> 
</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>
<?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="'<b style="color:red">'"/>
</xsl:template>
<xsl:template match="hitEnd">
<xsl:value-of disable-output-escaping="yes" select="'</b>'"/>
</xsl:template>
</xsl:transform>