2009-05-20 2 views
22

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

Пример:

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

становится

<div class="test" /> 

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

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

+0

Эта статья очень помогла мне понять этот вопрос http://webkit.org/blog/68/understanding-html-xml-and-xhtml/ – Ryan

ответ

11

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

+0

проблема в том, что TextWriter является абстрактным. – 2009-05-20 14:52:39

+1

Хорошо, я только что нашел о HtmlTextWriter (из ASP.net - System.Web.UI). Я думаю, что он содержит решение. TY. – 2009-05-20 15:23:31

+0

the easy I найдено создание нового класса XmlTextWriter и переопределение метода WriteEndElement, следует полный ответ https://stackoverflow.com/a/48896012/540063 – gblmarquez

21

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

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

<xsl:output method="html"/> 
+2

Это dosen't похоже на работу. Я пробовал различные комбинации , но он продолжает давать мне xml. – 2009-05-20 13:18:36

+0

У вас есть две записи ? Я не использую .NET, но Xalan в Java позволяет это –

+0

Нет, это не мое дело. – 2009-05-20 14:52:58

2

Вы не можете сказать, ваш браузер обрабатывать недопустимый 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> 

См

и т.д.

+0

У меня есть только пространство имен по умолчанию: xmlns: xsl = "http://www.w3.org/1999/XSL/Transform Как вы сказали, я думаю, что он переключился на xml. – 2009-05-20 13:19:26

+0

Я имел в виду пространство имен в ваших исходных данных документ, а не документ XSLT. –

+0

Ах, извините, я не использую пространство имен в документе soruce. Я думаю, что это факт, что я использую XmlTextWriter, который заставляет «поведение xml». В любом случае, большое вам спасибо за ваш помогите и для вашего времени. – 2009-05-20 18:00:53

2

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

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

Я использовал, чтобы положить <xsl:text> элемент внутри, как:

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

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

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

это не очень soloution, но это работает :-)

/Sten

+1

Это решение идеально подходит для меня. Спасибо – boothinator

+1

Довольно как моя мама! Спасибо за это! – maryisdead

0

Только что испытал ту же проблему с 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" /> 
+1

Кажется, что вы отвечаете на другой вопрос: как получить самозакрывающийся тег вместо не закрытого тега. OP спрашивает, как получить закрытый, не самозакрывающийся тег вместо самозакрывающегося тега. Я прав? – LarsH

1

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

  1. В вашем использовании XSL < XSL: метод вывода = 'HTML'>
  2. набор OutputSettings в выходном XmlWriter
  3. в Html внутри вашего xsl, не устанавливайте атрибуты в теге html, как это < html xmlns = "http://www.w3.org/1999/xhtml"> , но используйте < 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()); 
+0

Использование метода вывода в таблице стилей было единственным решением, которое сработало для меня. Мне нужно преобразовать XML через таблицу стилей в HTML и не смог использовать объект XmlWriter, только HtmlTextWriter, который не имеет одинаковых настроек. Короче говоря, это работало для меня, хотя я не люблю это так, как если бы я мог сделать это программно. –

0

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

<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/

0

Простым способом я создал новый класс 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(); 
    } 
}