Я использую XSLT для извлечения некоторого содержимого HTML со специальными символами (например,
) из файла XML. Содержимое хранится в узлах <content>
. Я определил такие специальные символы как: <!ENTITY nbsp " ">
, поэтому это выражение отлично работает:
<xsl:copy-of select="content" disable-output-escaping="yes"/>
Теперь я хочу добавить target="_blank"
к каждой ссылке, найденной в этом контенте. Это решение, с которым я столкнулся:
<xsl:template match="a" mode="html"> <a> <xsl:attribute name="href"><xsl:value-of select="@*"/></xsl:attribute> <xsl:attribute name="target">_blank</xsl:attribute> <xsl:apply-templates select="text()|* "/> </a> </xsl:template>
И вместо элемента «copy-of» я использую это:
<xsl:apply-templates select="content" mode="html"/>
Теперь все эти специальные символы (и nbsp тоже) исчезли с выхода. Как их сохранить? Кажется, disable-output-escaping="yes"
здесь не помогает.
Хорошо, я использую класс XSLTProcessor в PHP. Атрибут disable-output-escaping
не дал ошибку на самом деле, но когда я удалил его, результат был таким же, со всеми nbsp, поэтому это не имело значения.
UPD. С шаблоном XSL, который я показал ранее, мой пример ввода:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE page SYSTEM "html-entities.xsl"> <content>There is a non-breaking <a href="http://localhost">space</a> inside.</content>
HTML-entities.xsl:
<?xml version="1.0" encoding="UTF-8"?> <!ENTITY nbsp " ">
PHP-код:
$xp = new XSLTProcessor(); $xsl = new DOMDocument(); $xsl->load($xsl_filename); $xp->importStylesheet($xsl); $xml_doc = new DOMDocument(); $xml_doc->resolveExternals = true; $xml_doc->load($xml_filename); $html = $xp->transformToXML($xml_doc);
Мой текущий выход:
There is anon-breaking <a href="http://localhost" target="_blank">space</a> inside.
Мой желаемый результат:
There is a non-breaking <a href="http://localhost" target="_blank">space</a> inside.
В основном, имеет ли исходный код входного документа XML ссылку на символ, например  
или ссылка на сущность, как
или такой символ буквально не имеет значения для XSLT и не имеет значения, как обрабатывается вход и как выглядит вывод; в основном XSLT работает на дереве с символами Unicode, хранящимися в текстовых узлах. По крайней мере, это теория, ваш PHP-код, похоже, работает с моделью дерева DOM, которая может хранить узлы ссылок на объекты, но даже тогда для XSLT это не имеет значения. В дереве ввода должны быть текстовые узлы, содержащие символы Unicode (один, если это может быть неразрывным символом пробела с Unicode 160), и если вы скопируете такой текст на вывод, в результирующем дереве есть текстовый узел с одинаковыми символами Юникода ,
Для метода вывода html
некоторые XSLT-процессоры (например, Saxon 6.5.5) могут оказать вам услугу, чтобы гарантировать, что символы, определенные как сущности в HTML, сериализуются с соответствующей ссылкой на сущность, но даже если они этого не делают, сериализация результата tree должен быть файлом с соответствующими символами Юникода, закодированным в соответствии с атрибутом encoding
элемента xsl:output
Ваш текущий результат, полностью лишающий персонажа (например, « There is anon-breaking
), для меня не имеет смысла.