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

Я использую xslt для преобразования xml в файл aspx. В xslt у меня есть тег скрипта для включения файла jquery.js. Чтобы заставить его работать с IE, тег скрипта должен иметь явный закрывающий тег. По какой-то причине это не работает с 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 type = "text/javascript" src = "jquery-1.2.6.js">
            // <![CDATA[ // ]]>
        </script>

Я думал, что <xsl:output method = "html" /> поможет, но, похоже, он не работает?

/ Йонас

Асинхронная передача данных с помощью sendBeacon в JavaScript
Асинхронная передача данных с помощью sendBeacon в JavaScript
В современных веб-приложениях отправка данных из JavaScript на стороне клиента на сервер является распространенной задачей. Одним из популярных...
Принципы ООП в JavaScript
Принципы ООП в JavaScript
Парадигма объектно-ориентированного программирования имеет 4 основных принципа,
Laravel с Turbo JS
Laravel с Turbo JS
Turbo - это библиотека JavaScript для упрощения создания быстрых и высокоинтерактивных веб-приложений. Она работает с помощью техники под названием...
Слишком много useState? Давайте useReducer!
Слишком много useState? Давайте useReducer!
Современный фронтенд похож на старую добрую веб-разработку, но с одной загвоздкой: страница в браузере так же сложна, как и бэкенд.
Типы данных JavaScript
Типы данных JavaScript
В JavaScript существует несколько типов данных, включая примитивные типы данных и ссылочные типы данных. Вот краткое объяснение различных типов данных...
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик Модуль flexbox, также известный как гибкий модуль разметки box, помогает эффективно проектировать и...
10
0
10 565
11

Ответы 11

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

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

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

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

Если вы создаете 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();

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

Это сделано намеренно, и единственный известный мне обходной путь - использовать собственный 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();
        }
    }
}

Те из вас, кто использовал 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) не был 'Не разрешено размещать более 1 URL :-p

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

Bart van Delft 23.07.2010 12:51

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

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

<textarea></textarea>

Окончательный вывод из узла был перенесен в мой jsp как: -

<textarea/>

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

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

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

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

<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 as (если скидка> 0),

<Discount/>

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

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

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

Вот что он создал:

<script...> </script>

Вместо

<script ... />.

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

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

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

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

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

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

Другие вопросы по теме