Проблема с самозакрывающимися тегами XSLT

Я использую xslt для преобразования xml-файла в html. Движок .net xslt продолжает обслуживать меня самозакрывающиеся теги для пустых тегов.

пример:

<div class="test"></div> 

становится

<div class="test" />

первый является допустимым html, в то время как последний является незаконным html и плохо отображает. Мой вопрос : Как сказать движку xslt (XslCompiledTransform) не использовать самозакрывающиеся теги.

Если это невозможно, как я могу сказать своему браузеру (IE6+ в этом случае) интерпретировать самозакрывающиеся теги правильно.

11 ответов


Если вы используете XmlWriter в качестве потока вывода, используйте HTMLTextWriter вместо этого. XMLWriter переформатирует вывод HTML обратно в XML.


изменить xsl:output метод html (вместо xml).

или добавьте его, если у вас еще нет элемента

<xsl:output method="html"/>

обойти можно вставить элемент комментария к формированию сил не закрывая себе:

<script type="text/javascript" src="nowhere.js">
<xsl:comment></xsl:comment>
</script>

это не довольно soloution, но он работает: -)

/ Sten



вы не можете сказать своему браузеру обрабатывать недопустимый HTML как HTML-вам повезло, что он вообще понимает искаженный HTML. :)

сделать это в вашей таблице стилей:

<xsl:output method="html"/>

но, если ваш исходный документ имеет пространства имен, это не будет делать трюк. Процессоры XSLT, похоже, молча изменяют метод вывода обратно в XML, если узлы пространства имен присутствуют в выходных данных.

вам нужно заменить все экземпляры <xsl:copy-of> и <xsl:copy> С творениями элементов только с местным именем, например

<xsl:template match="*">
   <xsl:element name="{local-name()}">
     <xsl:apply-templates/>
   </xsl:element>
</xsl:template>

посмотреть

etc.


для меня это была проблема в скрипт - тег. Я решил это, заполнив его точкой с запятой (;)

<script type="text/javascript" src="somewhere.js">;</script>

раньше я ставил <xsl:text> элемент внутри, как:

<script type="text/javascript" src="/scripts/jquery.js"><xsl:text> </xsl:text></script>

есть несколько вещей, которые вы должны быть осторожны:

  1. в вашем использовании xsl
  2. set OutputSettings в вашем выходе XmlWriter
  3. в Html внутри вашего xsl не устанавливайте атрибуты в HTML-теге, как это но вместо этого используйте .

Это фрагмент рабочего кода:

string xmlStr = "<?xml version='1.0' encoding='UTF-8'?><Data></Data>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlStr);
string xslContents = @"
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'  
xmlns:msxsl='urn:schemas-microsoft-com:xslt' exclude-result-prefixes='msxsl'>
<xsl:output method='html' version='4.0' omit-xml-declaration='yes' indent='yes'/>
<xsl:template match='Data'>
<html>
<body>
    <div></div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>";
XslCompiledTransform xsl = new XslCompiledTransform();
xsl.Load(XmlReader.Create(new StringReader(xslContents)));
StringWriter result = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(result, xsl.OutputSettings))
{
    xsl.Transform(doc, null, writer);
}
System.Diagnostics.Debug.Write( result.ToString());

просто испытал ту же проблему с XSL PHP 5, с выходом/@method=html. Кажется, что присвоение пустого значения атрибута приведет элементов для вывода недействительной не самозакрывающиеся, не закрытые тегами:

<input type="text" name="foo" value="{my-empty-value}" />

результаты:

<input type="text" name="foo" value="">

одним из возможных решений является условное добавление атрибута:

<xsl:if test="string-length(my-empty-value) > 0">
    <xsl:attribute name="value">
        <xsl:value-of select="my-empty-value" />
    </xsl:attribute>
</xsl:if>

в результате:

<input type="text" name="foo" />

Я использую следующее, когда хочу предотвратить самозакрывание элемента:

<xsl:value-of select="''" />

это дурачит механизм рендеринга, полагая, что внутри элемента есть контент, и поэтому предотвращает самозакрывание.

это немного уродливое исправление, поэтому я рекомендую содержать его в описательном шаблоне и вызывать его каждый раз:

<xsl:template name="PreventSelfClosure">
   <xsl:value-of select="''" />
</xsl:template>


<div class="test">
   <xsl:call-template name="PreventSelfClosure"/>
</div>

Это затем отобразит следующий:

<div class="test"></div>

http://curtistimson.co.uk/post/xslt/how-to-prevent-self-closing-elements-in-xslt/


простой способ, который я нашел, - создать новый класс XmlTextWriter для переопределения метода WriteEndElement, принудительно закрывая тег и передавая процесс сериализации как параметр.

public class MyXmlTextWriter : XmlTextWriter
{
    public MyXmlTextWriter(Stream stream) : base(stream, Encoding.UTF8)
    { }
    public MyXmlTextWriter(TextWriter stream) : base(stream)
    { }

    public override void WriteEndElement()
    {
        base.WriteFullEndElement();
    }
}