代码之家  ›  专栏  ›  技术社区  ›  Tadmas

xsltproc不按名称选择元素

  •  4
  • Tadmas  · 技术社区  · 15 年前

    这是我的XHTML源文档(没什么好惊讶的):

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta name="generator" content=
    "HTML Tidy for Windows (vers 25 March 2009), see www.w3.org" />
    ...
    </body>
    </html>
    

    实际内容并不重要,我将在下面演示。顺便说一句,我很确定文档的格式很好,因为它是通过 tidy -asxml

    我的更复杂的XPath表达式没有返回任何结果,因此作为一个健全性测试,我试图非常简单地使用以下样式表对其进行转换:

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
        <xsl:template match="/">
            <xsl:text>---[</xsl:text>
            <xsl:for-each select="html">
                <xsl:text>Found HTML element.</xsl:text>
            </xsl:for-each>
            <xsl:text>]---</xsl:text>
        </xsl:template>
    </xsl:stylesheet>
    

    转换是通过 xsltproc --nonet stylesheet.xsl input.html ,输出为:“--[]--”(即,未找到 html ). 但是,如果我改变 for-each 节到:

    <xsl:for-each select="*">
        <xsl:value-of select="name()"/>
    </xsl:for-each>
    

    然后我得到“--[html]--”。同样,如果我用 for-each select="*/*"

    为什么它可以通过 * name() 提供正确的名称)但它不会直接使用元素名称找到它?

    3 回复  |  直到 15 年前
        1
  •  6
  •   Frédéric Hamidi    15 年前

    这个 html 源XML中的元素定义命名空间。您必须将它包含在匹配表达式中,并在 xsl:stylesheet 元素:

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:html="http://www.w3.org/1999/xhtml">
        <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
        <xsl:template match="/">
            <xsl:text>---[</xsl:text>
            <xsl:for-each select="html:html">
                <xsl:text>Found HTML element.</xsl:text>
            </xsl:for-each>
            <xsl:text>]---</xsl:text>
        </xsl:template>
    </xsl:stylesheet>
    
        2
  •  4
  •   Dimitre Novatchev    15 年前

    更改样式表

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
        <xsl:output method="text" omit-xml-declaration="yes" indent="no"/> 
        <xsl:template match="/"> 
            <xsl:text>---[</xsl:text> 
            <xsl:for-each select="html"> 
                <xsl:text>Found HTML element.</xsl:text> 
            </xsl:for-each> 
            <xsl:text>]---</xsl:text> 
        </xsl:template> 
    </xsl:stylesheet> 
    

    :

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:x="http://www.w3.org/1999/xhtml"
    > 
        <xsl:output method="text" omit-xml-declaration="yes" indent="no"/> 
        <xsl:template match="/"> 
            <xsl:text>---[</xsl:text> 
            <xsl:for-each select="x:html"> 
                <xsl:text>Found HTML element.</xsl:text> 
            </xsl:for-each> 
            <xsl:text>]---</xsl:text> 
        </xsl:template> 
    </xsl:stylesheet> 
    

    解释 :

    XML文档已声明默认命名空间: "http://www.w3.org/1999/xhtml" ,以及从声明此默认命名空间的顶级元素派生的所有未固定节点都属于此命名空间。

    因此 <xsl:for-each select="html"> 指令将选择并应用其主体 html 属于“no namespace”的元素--文档中没有这样的元素--只有 html格式 元素不属于xhtml命名空间。

    :

    不能未固定地引用属于默认命名空间的名称。因此,我们需要将前缀绑定到这样一个元素所属的命名空间。如果这个前缀是 "x:" ,那么我们可以引用任何这样的元素 具有 “x:” .

        3
  •  1
  •   Jarekczek    13 年前

    不声明命名空间的解决方法,以便样式表接受任何命名空间:

    <xsl:template match="*[name()='html']" >