Явный script конечный тег всегда преобразуется в самозакрывающийся

Я использую xslt для преобразования xml в aspx файл. В xslt у меня есть тег script, который включает файл jquery.js. Чтобы заставить его работать с IE, тег script должен иметь явный закрывающий тег. По какой-то причине это не работает с xslt ниже.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
    xmlns:asp="remove">    
    <xsl:output method="html"/>
    <xsl:template match="/">
        <html xmlns="http://www.w3.org/1999/xhtml">
            <head>
                <title>TEST</title>
                <script type="text/javascript" src="jquery-1.2.6.js"></script>

Но если я изменю тег script, как показано ниже, он будет работать.

        <script type="text/javascript" src="jquery-1.2.6.js">
            // <![CDATA[ // ]]>
        </script>

Я думал, что <xsl:output method="html" /> выполнит трюк, но он не работает?

/Jonas

Ответ 1

Если вы создаете XmlWriter самостоятельно, вам нужно передать преобразование OutputSettings в XmlWriter, например:

XmlDocument doc = new XmlDocument();
doc.LoadXml("<book><author>Trudi Canavan</author><title>Voice of the Gods</title></book>");

XslCompiledTransform transform = new XslCompiledTransform();
transform.Load("XSLTFile1.xslt");

StringBuilder output = new StringBuilder();

// Here we pass the output setting to the writer, otherwise the transform
// may be set to Html, but the XmlWriter will be outputting Xml
XmlWriter writer = XmlWriter.Create(output, transform.OutputSettings);

transform.Transform(doc, writer);

Console.WriteLine(output.ToString());
Console.ReadKey();

Ответ 2

Это довольно распространенная проблема при создании HTML из XSLT. Я подозреваю, что корень проблемы заключается в том, что сам XSLT является XML-документом. Несмотря на то, что вы начинаете с вашей XSLT-программы в виде сериализованного XML, к тому времени, когда XSLT-процессор получит ее, она уже была де-сериализована для представления "infoset". На уровне XML пустой тег и самозакрывающийся эквивалент; у элемента довольно просто нет детей. Это означает, что ваш XSLT-процессор, вероятно, никогда не увидит версию программы, в которой элемент script имеет как открывающий, так и закрывающий тег.

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

Кстати, речь идет не о том, чтобы сделать IE счастливым. Если вы посмотрите на спецификацию HTML, вы обнаружите, что конечный тег не требуется. Я уверен, что некоторые люди посчитают это ироничным, что IE правильно его реализует.: -)

Ответ 3

Я нашел этот ответ на сайте форума MSDN:

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

Если вы добавили вышеуказанный код xslt до конца вашего файла xsl, он заставляет элемент иметь некоторый контент (пробел в этом случае) вместо самозакрывания. Пробовал это, и это сработало.

Это то, что он создал:

<script...> </script>

вместо

<script ... />.

Ответ 4

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

public class HtmlTextWriter : XmlTextWriter
{
    private readonly string[] fullEndElements = 
        new string[] { "script", "title" };

    private string lastStartElement = null;


    public HtmlTextWriter(TextWriter textWriter)
        : base(textWriter)
    {
    }

    public HtmlTextWriter(string filename, Encoding encoding)
        : base(filename, encoding)
    {
    }

    public HtmlTextWriter(Stream w, Encoding encoding)
        : base(stream, encoding)
    {
    }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        lastStartElement = localName;
        base.WriteStartElement(prefix, localName, ns);
    }

    public override void WriteEndElement()
    {
        if (Array.IndexOf(fullEndElements, lastStartElement) > -1)
        {
            base.WriteFullEndElement();
        }
        else
        {
            base.WriteEndElement();
        }
    }
}

Ответ 5

Ответ Барта ван Делфтса указал мне в правильном направлении с этим, так что он приветствует намек!

У меня была и эта проблема, используя [javax.xml.transform.Transformer] Всякий раз, когда я пытался разобрать фрагмент отформатированного html, в моем случае: -

<textarea></textarea>

конечный вывод из Node вносился в мой jsp как: -

<textarea/>

который явно закручивал любой следующий код из-за того, что он рассматривался как больше содержимого элемента textarea.

настройка t.setOutputProperty(javax.xml.transform.OutputKeys.METHOD, "html");, похоже, обеспечила самозакрывающееся поведение, которое я ожидал. Это свойство по умолчанию является "xml" из моего собственного тестирования, поэтому, очевидно, что тег xml без узлов под ним совершенно счастлив как закрытие себя.

Надеюсь, это все равно поможет.

Ответ 6

рассмотрим этот пример,

<Discount>
       <!--<xsl:if test="Discount>0">-->
             <xsl:value-of select="Discount"/>
       <!--</xsl:if>-->
</Discount>

Если я работаю со скидкой на продукт. и я проверяю его перед использованием. он вернет выход,

<Discount>value of the discount</Discount>

Но если я не комментирую приведенный выше пример,

<Discount>
       <xsl:if test="Discount>0">
             <xsl:value-of select="Discount"/>
       </xsl:if>
</Discount>

он вернет o/p после xslt как (если скидка равнa > 0),

<Discount/>

Ответ 7

И это, конечно, против двигателя MS XSLT? Как странно. Я не могу сказать, что я столкнулся с этим в .NET 1.1 или 2.0, и у меня есть ряд преобразований, которые делают то же самое, поэтому я предлагаю вам пойти с простым обходным путем.

Ответ 8

Я использовал комментарий перед тегом script end, чтобы пройти эту проблему.

Ответ 9

Для тех из вас, кто использует Xalan 2.7.0 (на Java), у меня была та же проблема. Я применил файл org/apache/xml/serializer/ToStream.java в исходном исходном коде, чтобы обойти эту проблему. Если вы укажете как outputProperty:

private static Properties XHTML() {
  Properties p = new Properties();
  p.setProperty(OutputKeys.METHOD, "xhtml");
  p.setProperty(OutputKeys.DOCTYPE_PUBLIC,
    "-//W3C//DTD XHTML 1.0 Strict//EN");
  p.setProperty(OutputKeys.DOCTYPE_SYSTEM,
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
  p.setProperty(OutputKeys.ENCODING, "UTF-8");
  p.setProperty("{http://xml.apache.org/xalan}indent-amount", "4");
  p.setProperty(OutputKeys.INDENT, "yes");
  p.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
  p.setProperty("{http://example.com}selfclosing","no");
  return p;
 }

Обратите внимание на последнюю строку на selfclosing. Это свойство, на которое отвечает эта обновленная версия ToStream.java и будет предотвращать теги <div /> и <script /> и выводить теги <div></div> и <script></script>. Он также включает в себя исключения из них, а именно те, которые указаны в стандарте HTML, разрешенные для самозакрывания (т.е. "area", "base", "basefont", "br", "col", "frame", "hr" img "," input "," link "," meta "," param"). Это работало для меня, по крайней мере, и теперь веб-страницы отлично отображаются в IE.

Новый файл ToStream.java можно найти в http://bvandelft.ruhosting.nl/ToStream.java и предварительно скомпилированную версию serializer.jar(работа с 2.7) также доступен по одному и тому же URL-адресу, но serializer.jar(в котором включена скомпилированная версия ToStream) не разрешено размещать более одного URL-адреса: -p

Ответ 10

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

<xsl:text disable-output-escaping="yes">
    &lt;script src="jquery-2.0.3.js"&gt;&lt;/script&gt;
</xsl:text>

Btw. Я думаю, что метод = "html" тоже должен сделать трюк, но вы не будете отображать xhtml, например, br не будет закрыто.

Ответ 11

Еще один быстрый взлом - добавить комментарий Javascript в тег:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">//</script>

Это просто добавит комментарий в конец script - будьте осторожны, чтобы вы ничего не прокомментировали по ошибке!