Проблема с самозакрывающимися тегами 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>
посмотреть
- http://www.biglist.com/lists/xsl-list/archives/200708/msg00538.html
- http://www.stylusstudio.com/xsllist/200509/post90860.html
- http://www.richardhallgren.com/removing-namespace-from-outgoing-messages/
etc.
для меня это была проблема в скрипт - тег. Я решил это, заполнив его точкой с запятой (;)
<script type="text/javascript" src="somewhere.js">;</script>
раньше я ставил <xsl:text>
элемент внутри, как:
<script type="text/javascript" src="/scripts/jquery.js"><xsl:text> </xsl:text></script>
есть несколько вещей, которые вы должны быть осторожны:
- в вашем использовании xsl
- set OutputSettings в вашем выходе XmlWriter
- в 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();
}
}