xsltproc не выбирает элементы по имени - PullRequest
4 голосов
/ 17 октября 2010

Я пытаюсь преобразовать XHTML с помощью таблицы стилей XSLT, но я даже не могу получить базовую таблицу стилей, которая бы соответствовала чему-либо. Я уверен, что упускаю что-то простое.

Вот мой исходный документ 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="*/*", я получаю «--- [headbody] ---», как я и ожидал.

Почему он может найти дочерний элемент через *name(), дающим правильное имя), но не может найти его, используя имя элемента напрямую?

Ответы [ 3 ]

6 голосов
/ 17 октября 2010

Элемент 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>
4 голосов
/ 17 октября 2010

Измените вашу таблицу стилей с :

<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", и все нефиксированные узлы, которые происходят от верхнего элемента, объявляющего это пространство имен по умолчанию, принадлежат этому пространству имен.

С другой стороны, в XPath любое нефиксированное имя считается принадлежащим «без пространства имен».

Следовательно, инструкция <xsl:for-each select="html"> выберет и применит свое тело ко всем элементам html, которые принадлежат "пространству имен" - и в документе их нет - единственный элемент html принадлежит пространство имен xhtml.

Решение

На имена, принадлежащие пространству имен по умолчанию, нельзя ссылаться без префикса. Поэтому нам нужно привязать префикс к пространству имен, которому принадлежит элемент. Если этот префикс "x:", то мы можем сослаться на любой такой элемент с префиксом с "x:".

0 голосов
/ 09 октября 2012

Обходной путь без объявления пространства имен, так что таблица стилей принимает любое пространство имен:

<xsl:template match="*[name()='html']" >
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...