Функция документа XSLT не работает в Chrome - PullRequest
0 голосов
/ 05 июня 2018

Я пытаюсь преобразовать XSLT с помощью Javascript и заставить его работать как в Chrome, так и в IE.Страница входа - a.html.Он отлично работает в IE (как в собственном режиме, так и в режиме совместимости), но не работает в Chrome правильно, т. Е. Раскрывающийся список не создается с параметрами.

В Chrome, однако, если я открою data.xml, который имеет:

<?xml-stylesheet type="text/xsl" href="render.xslt" ?>

прямо в хроме, он отлично трансформируется.Но если я попытаюсь сделать то же самое с помощью XSLTProcessor, это не сработает.В частности, функция document не работает.Не могли бы вы помочь?

Мой код выглядит следующим образом.

Javascript:

var MSXML2_DOMDocument_6 = "MSXML2.DOMDocument.6.0";
function tranform(xml, xsl) {
    if (window.ActiveXObject || "ActiveXObject" in window) {
        var xmlSerializer = new XMLSerializer();
        var xmlString = xmlSerializer.serializeToString(xml);
        var xslString = xmlSerializer.serializeToString(xsl);

        var xsl = new ActiveXObject(MSXML2_DOMDocument_6);
        xsl.setProperty("AllowXsltScript", true);
        xsl.setProperty("AllowDocumentFunction", true);
        xsl.resolveExternals = true;
        xsl.async = false;
        xsl.loadXML(xslString);

        var xml = new ActiveXObject(MSXML2_DOMDocument_6);
        xml.resolveExternals = true;
        xml.preserveWhiteSpace = true;
        xml.async = false;
        xml.loadXML(xmlString);
        xml.resolveExternals = true;

        ex = xml.transformNode(xsl);
        document.getElementById("example").innerHTML = ex;
    } else if (document.implementation && document.implementation.createDocument) {
        xsltProcessor = new XSLTProcessor();
        xsltProcessor.importStylesheet(xsl);
        resultDocument = xsltProcessor.transformToFragment(xml, document);
        document.getElementById("example").appendChild(resultDocument);
    }
}

function loadXMLDoc() {

    $.ajax({
        method: "GET",
        url: "data.xml",
        dataType: "xml"
    }).then(function (xml) {
            console.log("done xml")
            $.ajax({
                method: "GET",
                url: "render.xslt",
                dataType: "xml"
            }).then(function (xsl) {
                console.log("done xsl")
                tranform(xml, xsl)
            })
        },
        function (e) {
            console.log("Got error in xml", e.status)
        })
}

$(loadXMLDoc)

foo / b.xml:

<dropdowns>
  <dropdown name="xyz">
    <option value="I">Info</option>
    <option value="C">Category</option>
  </dropdown>
</dropdowns>

data.xml:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="render.xslt" ?>
<catalog name="xyz" />

a.html:

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="jquery-3.3.1.js"></script>
    <title>Document</title>
</head>

<body>
    <div id="example"></div>
    <script src="b.js"></script>
</body>

</html>

render.xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:import href="util.xslt" />
    <xsl:output method="html"></xsl:output>
    <xsl:template match="/">
        <h1>
            <xsl:value-of select="/catalog/@name"></xsl:value-of>
        </h1>
        <xsl:call-template name="dropdown">
            <xsl:with-param name="listname">xyz</xsl:with-param>
            <xsl:with-param name="value" select="/catalog/@name"/>
        </xsl:call-template>
    </xsl:template>
</xsl:stylesheet>

util.xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html"></xsl:output>
    <xsl:template name="dropdown">
        <xsl:param name="listname"/>
        <xsl:param name="value"/>
        <select>
            <xsl:for-each select="document('foo/b.xml')/dropdowns/dropdown[@name=$listname]/option">
                <option>
                    <xsl:attribute name="value">
                        <xsl:value-of select="@value"/>
                    </xsl:attribute>
                    <xsl:value-of select="."/>
                </option>
            </xsl:for-each>
        </select>
    </xsl:template>
</xsl:stylesheet>

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

Пожалуйста, дайте мне знать, если требуется какое-либо разъяснение.

Ответы [ 3 ]

0 голосов
/ 14 июня 2018

Я нашел обходной путь [1] для этой проблемы.

В chrome <xsl:import> работает правильно при преобразовании в Javascript.Итак, я преобразовал свой XML в XSL <xsl:choose> с <xsl:when> для каждого тега dropdown.

Обновление util.xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html"></xsl:output>
    <xsl:template name="dropdown">
        <xsl:param name="listname"/>
        <xsl:param name="value"/>
        <select>
            <xsl:choose>
                <xsl:when name="$listname='xyz'">
                    <option value="I">Info</option>
                    <option value="C">Category</option>
                </xsl:when>
            </xsl:choose>
        </select>
    </xsl:template>
</xsl:stylesheet>

1.Я согласен, что это не очень хороший обходной путь и, конечно, не обобщенный.Если у кого-то есть лучшее решение, пожалуйста, опубликуйте его как ответ.

0 голосов
/ 14 июня 2018

Это известная проблема, открытая с 2009 года. Кроме того, команда Chrome даже не планирует ее исправлять, она планирует удалить ее поддержку из Chrome (не знаю, когда).Но есть один способ обойти эту проблему.преобразуйте ваши xml-данные в xslt, а затем вы можете импортировать их в таблицу стилей.

, чтобы ваш код javaScript не изменился.

foo / b.xml станет foo / b.xslt

 <?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template name="dropdowns">
    <xsl:param name="listname"/>
    <xsl:param name="value"/>
    <xsl:choose>
        <xsl:when test="$listname='xyz'">
            <xsl:call-template name="option">
                <xsl:with-param name="value">I</xsl:with-param>
                <xsl:with-param name="label">Info</xsl:with-param>
                <xsl:with-param name="selectedValue" select="$value"/>
            </xsl:call-template>
            <xsl:call-template name="option">
                <xsl:with-param name="value">C</xsl:with-param>
                <xsl:with-param name="label">Category</xsl:with-param>
                <xsl:with-param name="selectedValue" select="$value"/>
            </xsl:call-template>
        </xsl:when>

    </xsl:choose>
 </xsl:template>

 <xsl:template name="option">
    <xsl:param name="label"/>
    <xsl:param name="value"/>
    <xsl:param name="selectedValue"/>
    <option value="{$value}">
        <xsl:if test="$value = $selectedValue">
            <xsl:attribute name="selected">selected</xsl:attribute>
        </xsl:if>
        <xsl:value-of select="$label"/>
    </option>
</xsl:template>
</xsl:stylesheet>

util.xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:import href="foo/b.xslt" />
<xsl:output method="html" />

<xsl:template name="dropdown">
    <xsl:param name="listname"/>
    <xsl:param name="value"/>
    <select>
        <xsl:call-template name="dropdowns">
            <xsl:with-param name="listname" select="$listname"/>
            <xsl:with-param name="value" select="$value"/>
        </xsl:call-template>
    </select>
</xsl:template>
</xsl:stylesheet>

render.xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:import href="util.xslt" />
<xsl:output method="html"></xsl:output>
<xsl:template match="/">
    <h1>
        <xsl:value-of select="/catalog/@name"></xsl:value-of>
    </h1>
    <xsl:call-template name="dropdown">
        <xsl:with-param name="listname">xyz</xsl:with-param>
        <xsl:with-param name="value">C</xsl:with-param>
    </xsl:call-template>
</xsl:template>
</xsl:stylesheet>

С этими изменениями вы можете создавать раскрывающиеся страницы на своей странице, которые будут работать как вIE и хром.

0 голосов
/ 12 июня 2018

В целом весь подход касается вложенных шаблонов.
Здесь уже дан ответ: Как пройти через вложенную структуру XML с использованием шаблонов

Ниже приведены еще некоторыевопросы и разъяснения по поводу комментариев ниже вопроса.

После настройки локального сервера, который доставляет файл util.xslt в качестве Content-Type text/css, как ожидается в Chrome вместо application/xslt+xml,Сценарии по-прежнему никогда не работают так, как ожидалось.Следовательно, должна быть еще одна проблема, связанная с Chrome.

enter image description here

Интересным моментом является то, что существует два xslt-документа, в то время как один передается и принимаетсяchrome с application/xslt+xml, а другой только как text/xml или text/xsl (да, оба приняты Chrome, я пробовал).

Поэтому интересный пост о версиях xml / xslt может оказаться бесполезным в отношении этой проблемы.

Ниже приведены подробные сообщения консоли:

enter image description here

Настройкасервер выполнен со следующими строками, которые изменяют Content-Type (mime-тип), если запрашиваемое имя файла имеет суффикс xslt, а ожидаемый mime-тип равен text/css:

<If "%{REQUEST_FILENAME} =~ m#\.xslt$# && %{HTTP:Accept} =~ m#^text\/css#">
    Header set "Content-Type" "text/css"
</If>

FireFox

Следует отметить, что firefox полностью скрывает util.xslt в сетевой панели:

enter image description here

Кроме того, Firefox принимает оба метода, ActiveXObject и XSLTProcessor.В зависимости от логики в JavaScript по умолчанию установлено значение ActiveXObject, эта версия выглядит также более плавно в отношении анимации раскрывающегося списка.

Firefox жалуется, когда для xml-версии установлено значение 1.1, поэтому игра с номерами версий можетне очень помогает повысить совместимость браузера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...