XSLT转换XHTML文档

3
我对XSLT比较陌生,但有人建议我使用它来完成某个任务。我有一堆xhtml文件,想要从中删除侧边栏。侧边栏包含在 <div class="foo"> 元素中。
我可以成功地执行标识变换,使用这个答案 中的说明。但是我似乎无法匹配到我想要删除的元素。也许这是因为它们不像我在找到的每个设计模式示例中那样成为顶级元素?
请问如何正确地从标识变换中删除<div class="foo">及其所有子元素?

好问题(+1)。请查看我的答案,其中包含详细的解决方案和说明。 - Dimitre Novatchev
1个回答

6

很可能您的问题是由源XHTML文件中存在默认(xhtml)命名空间引起的(您没有向我们展示,因此这只是一个猜测)。

有人能解释一下从身份转换中删除<xhtml>及其所有子元素的正确方法吗?

以下是在存在默认命名空间的情况下执行此操作的方法:

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

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

 <xsl:template match="xhtml:div[@class='foo']"/>
</xsl:stylesheet>

当对以下XHTML文档应用此转换时

<html xmlns="http://www.w3.org/1999/xhtml">
    <div class="class1">
        <p>Text1</p>
    </div>
    <div class="foo">
        <p>Text foo</p>
    </div>
    <div class="class2">
        <p>Text2</p>
    </div>
</html>

期望的正确结果已经生成:

<html xmlns="http://www.w3.org/1999/xhtml">
   <div class="class1">
      <p>Text1</p>
   </div>
   <div class="class2">
      <p>Text2</p>
   </div>
</html>

在模板的匹配表达式中使用命名空间前缀是必要的,因为XPath将任何未命名的名称视为“无命名空间”,而具有非前缀名称的匹配表达式不匹配任何节点,因为它指定了“无命名空间”的节点,但源文档的所有节点都在XHTML命名空间中。
如果源文档中没有默认命名空间,则可以简化转换:
当对以下XML文档应用此转换时(请注意,它不定义默认命名空间):
<html>
    <div class="class1">
        <p>Text1</p>
    </div>
    <div class="foo">
        <p>Text foo</p>
    </div>
    <div class="class2">
        <p>Text2</p>
    </div>
</html>

期望的正确结果已生成:

<html>
   <div class="class1">
      <p>Text1</p>
   </div>
   <div class="class2">
      <p>Text2</p>
   </div>
</html>

两种转换都使用身份规则来复制文档中的任何节点以及另一个模板,该模板覆盖了对匹配"div[@class='foo']"的节点的身份规则。这个第二个模板是空的(没有主体),这意味着匹配的节点和以它为根的子树根本没有被处理(被忽略),因此不会出现在输出中。


你的代码可以运行,但是为什么这个不行:<xsl:output omit-xml-declaration="no" indent="yes" method="xml" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" /> - jbtx
最终我使用了两个样式表:一个用于剥离元素,第二个用于添加正确的DTD声明。 - jbtx
@jbtx:为什么?这对我有用。我在输出开头得到:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">。也许你的XSLT处理器出了问题?我的结果由Saxon 6.5.4、MSXML 3-6、AltovaXML (XML-SPY)、Saxon 9.1.07和XML-SPY-XSLT2.0生成。如果你正在使用其中两个可用的.NET XSLT处理器,则必须微调传递给“Transform()方法的XmlWriter`参数的设置。阅读你的文档。 - Dimitre Novatchev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接