Как я могу распечатать документ результатов XSLT с удаленными исходными элементами?

У меня есть исходный документ XHTML с элементами в нескольких пространствах имен, которые я преобразовываю в HTML-документ (очевидно, без пространств имен). В моих XSL-шаблонах я сопоставляю только элементы пространства имен XHTML, чтобы удалить элементы, не совместимые с HTML, из дерева результатов. Однако на выходе, в то время как эти элементы исчезли, пробелы, которые я использовал для их отступов, остаются, т. Е. Строк нерелевантных CR / LF и вкладок.

Например, если это мой ввод:

<div id="container"> <svg:svg> <svg:foreignObject> <img /> </svg:foreignObject> </svg:svg> </div> 

После применения преобразования это будет выход:

 <div id="container"> <img /> </div> 

Хотя мой желаемый результат:

 <div id="container"> <img /> </div> 

Это происходит с использованием TransforMiiX (прикрепление таблицы стилей локально в Firefox) и libxslt (прикрепление таблицы стилей к серверу с PHP), поэтому я знаю, что это, вероятно, результат того, что некоторый параметр XSL не устанавливается, но я попытался сыграть с <xsl:output indent="yes|no" /> , xml:space="default|preserve" , <xsl:strip-space elements="foo bar|*" /> , все безрезультатно.

Это будет реализовано на стороне сервера, поэтому, если нет способа сделать это в необработанном XSL, но есть способ сделать это в PHP, я соглашусь с этим.

Я знаю, что это не проблема пространства имен, так как я получаю тот же результат, если я удаляю ЛЮБОЙ элемент.

Белое пространство, которое вы видите, находится в исходном документе. Стандарты по умолчанию XSLT говорят, что текстовые узлы должны быть скопированы, неважно, пусты ли они или нет. Чтобы переопределить правило по умолчанию, включите:

 <xsl:template match="text()" /> 

Альтернативно: <xsl:apply-templates select="node()" /> <xsl:apply-templates /> (или <xsl:apply-templates select="node()" /> ) и явно укажите, к каким дочерним элементам вы хотите применить шаблоны. Этот метод может потребоваться, если ваше преобразование частично зависит от шаблона идентификации (в этом случае пустой шаблон для текстовых узлов будет контрпродуктивным).

Я выделил «незначительное» белое пространство в вашем фрагменте, как Word это сделает:

 <div id="container">¶ ····<svg:svg>¶ ········<svg:foreignObject>¶ ············<img />¶ ········</svg:foreignObject>¶ ····</svg:svg>¶ </div> 

EDIT: вы также можете изменить шаблон своей личности следующим образом:

 <xsl:template match="node() | @*"> <xsl:copy> <!-- select everything except blank text nodes --> <xsl:apply-templates select=" node()[not(self::text())] | text()[normalize-space() != ''] | @* " /> </xsl:copy> </xsl:template> 

Это удалит пустой текстовый узел (значения атрибута остаются нетронутыми, они не являются текстовыми узлами). Используйте <xsl:output indent="yes" /> чтобы печатать результат.

У вас есть два пути для достижения желаемого результата: либо вы исправляете свое первоначальное преобразование, чтобы обрабатывать пустоты по-разному, либо сохраняете свою трансформацию как есть, и добавляете второй проход, чтобы префикс вывода. Если ваше первоначальное преобразование осложнено, я бы рекомендовал использовать 2-проходный подход. Вы не хотите, чтобы ваше преобразование было еще более сложным, или вы создадите некоторые угловые случаи, когда вы не получите желаемых результатов, и вам придется добавить более специальную обработку дела и потенциально добавить ошибки к чему-то, что раньше работало , и т.д…

Вы должны иметь возможность игнорировать узлы пробелов, тестируя их с помощью normalize-text() . Вот как мог бы выглядеть второй проход. Если вы пойдете с 1-проходным подходом, код будет примерно таким же, как я предполагаю.

 <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" /> <xsl:template match="text()"> <xsl:if test="normalize-space(.) != ''"> <xsl:value-of select="."/> </xsl:if> </xsl:template> <xsl:template match="node()"> <xsl:copy> <xsl:copy-of select="@*" /> <xsl:apply-templates /> </xsl:copy> </xsl:template> </xsl:stylesheet>