Safari не обрабатывает HTML из XSL так же - PullRequest
1 голос
/ 08 октября 2011

У меня есть main.xml, который я открываю в браузере Safari. Он отлично обрабатывается XSL-файлом, указанным вверху.

У меня есть некоторый javascript на получившейся странице, который должен взять второй файл XML и обработать его, используя указанный XSL в вызове href.

XSL во втором файле category.xml, кажется, работает нормально (о чем свидетельствует предупреждение), но когда он вставляется как дочерний элемент в div contentbody, он не отображается должным образом.

Чтобы показать, как это должно выглядеть, я скопировал выходные данные второго XSL-процесса из диалогового окна предупреждения в первоначально отображаемый div contentbody. Выглядит хорошо, так же как и элемент ul. При замене его на вывод XSL это очень неправильно.

Я был бы очень признателен за помощь. Почему Safari (Mac OS Lion и iPad для мобильных устройств Safari) не отображает вставленный HTML-вывод XSL, правильно выполненный в Javascript? Как мне это исправить?

Спасибо,

Мт.

main.xml

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="main.xslt"?>
<Feed xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
  <Status>OK</Status>
  <Result>
    <FeedDTO>
      <Id>2286</Id>
      <Name>Free to view</Name>
      <IconName />
    </FeedDTO>
    <FeedDTO>
      <Id>2320</Id>
      <Name>Latest news</Name>
      <IconName />
    </FeedDTO>
    <FeedDTO>
      <Id>2249</Id>
      <Name>Some reviews</Name>
      <IconName />
    </FeedDTO>
    <FeedDTO>
      <Id>2250</Id>
      <Name>The wrap</Name>
      <IconName />
    </FeedDTO>
  </Result>
</Feed>

main.xsl

<?xml version="1.0" encoding="iso-8859-1"?>

<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:msws="http://tempuri.org/"
    >

  <xsl:template match="/">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>main</title>
        <link href="StyleSheet1.css" rel="stylesheet" type="text/css" />
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
        <script type="text/javascript">
            function transform(xmlfile,xslfile)
            {
                var xmlRequest = new XMLHttpRequest();
                xmlRequest.open("GET", xmlfile, false);
                xmlRequest.send(null);
                xml= xmlRequest.responseXML;

                var xslRequest = new XMLHttpRequest();
                xslRequest.open("GET", xslfile, false);
                xslRequest.send(null);
                xsl = xslRequest.responseXML;

                xsltProcessor = new XSLTProcessor();
                xsltProcessor.importStylesheet(xsl);

                resultDocument = xsltProcessor.transformToFragment(xml,document);
                document.getElementById("contentbody").appendChild(resultDocument);
            }

            function go(xmlfile,xslfile)
            {
                var xmlRequest = new XMLHttpRequest();
                xmlRequest.open("GET", xmlfile, false);
                xmlRequest.send(null);
                xml= xmlRequest.responseXML;

                var xslRequest = new XMLHttpRequest();
                xslRequest.open("GET", xslfile, false);
                xslRequest.send(null);
                xsl = xslRequest.responseXML;
                xsltProcessor=new XSLTProcessor();
                xsltProcessor.importStylesheet(xsl);
                resultDocument = xsltProcessor.transformToFragment(xml,document);
                document.getElementById("contentbody").innerHTML = "";
                document.getElementById("contentbody").appendChild(resultDocument);
            }

            function loadXMLDoc(dname)
            {
                if (window.XMLHttpRequest)
                {
                    xhttp=new XMLHttpRequest();
                }
                else
                {
                    xhttp=new ActiveXObject("Microsoft.XMLHTTP");
                }
                xhttp.open("GET",dname,false);
                xhttp.send("");
                return xhttp.responseXML;
            }

            function displayResult(xmlfile,xslfile)
            {
                xml=loadXMLDoc(xmlfile);
                xsl=loadXMLDoc(xslfile);
                xsltProcessor=new XSLTProcessor();
                xsltProcessor.importStylesheet(xsl);
                resultDocument = xsltProcessor.transformToFragment(xml,document);
                document.getElementById("contentbody").innerHTML = "";
                document.getElementById("contentbody").appendChild(resultDocument);
                alert(document.getElementById("contentbody").innerHTML);
            }
        </script>
      </head>
      <body>
        <div id="main">
          <div id="menu">
            <div id="categorytitle">
              Categories
            </div>
            <ul id="categorybody">
              <xsl:for-each select="*/*/msws:FeedDTO">
                <xsl:if test="msws:Name != 'Free to view'">
                  <li id="menuitem">
                    <xsl:element name="a">
                      <xsl:attribute name="href">javascript:void(0)</xsl:attribute>
                      <xsl:attribute name="onclick">
                        displayResult('category.xml','category.xslt');
                      </xsl:attribute>
                      <xsl:value-of select="substring(msws:Name, 1, 100)"/>
                    </xsl:element>
                  </li>
                </xsl:if>
              </xsl:for-each>
            </ul>
          </div>
          <div id="content">
            <div id="contenttitle">
              Content
            </div>
            <div id="contentbody"><!-- CONTENT HERE COPIED FROM ALERT TO SHOW WHAT IT SHOULD LOOK LIKE -->
              <div xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msws="http://tempuri.org/"><ul id="categorybody"><li id="categoryitem"><a href="javascript:void(0)" onclick="
                XsltTransform('article.xml','article.xslt');
              ">The first title</a></li><li>07 Oct 2011</li><li>A nice long description 1.</li><li id="categoryitem"><a href="javascript:void(0)" onclick="
                XsltTransform('article.xml','article.xslt');
              ">The second title</a></li><li>06 Oct 2011</li><li>A nice long description 2.</li><li id="categoryitem"><a href="javascript:void(0)" onclick="
                XsltTransform('article.xml','article.xslt');
              ">The third title</a></li><li>06 Oct 2011</li><li>A nice long description 3.</li><li id="categoryitem"><a href="javascript:void(0)" onclick="
                XsltTransform('article.xml','article.xslt');
              ">The fourth title</a></li><li>05 Oct 2011</li><li>A nice long description 4.</li><li id="categoryitem"><a href="javascript:void(0)" onclick="
                XsltTransform('article.xml','article.xslt');
              ">The fifth title</a></li><li>04 Oct 2011</li><li>A nice long description 5.</li></ul></div>
            </div>
          </div>
        </div>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

content.xml

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="category.xslt"?>
<Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
  <Status>OK</Status>
  <Result>
    <ResultItems>
      <ArticleLiteDTO>
        <Id>2913935</Id>
        <Title>The first title</Title>
        <Description>A nice long description 1.</Description>
        <PublishedDate>2011-10-07T00:00:00</PublishedDate>
        <SmallImageUrl />
        <LargeImageUrl />
      </ArticleLiteDTO>
      <ArticleLiteDTO>
        <Id>2913226</Id>
        <Title>The second title</Title>
        <Description>A nice long description 2.</Description>
        <PublishedDate>2011-10-06T00:00:00</PublishedDate>
        <SmallImageUrl />
        <LargeImageUrl />
      </ArticleLiteDTO>
      <ArticleLiteDTO>
        <Id>2913137</Id>
        <Title>The third title</Title>
        <Description>A nice long description 3.</Description>
        <PublishedDate>2011-10-06T00:00:00</PublishedDate>
        <SmallImageUrl />
        <LargeImageUrl />
      </ArticleLiteDTO>
      <ArticleLiteDTO>
        <Id>2912539</Id>
        <Title>The fourth title</Title>
        <Description>A nice long description 4.</Description>
        <PublishedDate>2011-10-05T00:00:00</PublishedDate>
        <SmallImageUrl />
        <LargeImageUrl />
      </ArticleLiteDTO>
      <ArticleLiteDTO>
        <Id>2911761</Id>
        <Title>The fifth title</Title>
        <Description>A nice long description 5.</Description>
        <PublishedDate>2011-10-04T00:00:00</PublishedDate>
        <SmallImageUrl />
        <LargeImageUrl />
      </ArticleLiteDTO>
    </ResultItems>
  </Result>
</Data>

content.xsl

<?xml version="1.0" encoding="iso-8859-1"?>

<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:msws="http://tempuri.org/"
    >

  <xsl:template match="/">
<div>
    <ul id="categorybody">
      <xsl:for-each select="*/*/*/msws:ArticleLiteDTO">
        <li id="categoryitem">

            <xsl:element name="a">
              <xsl:attribute name="href">javascript:void(0)</xsl:attribute>
              <xsl:attribute name="onclick">
                XsltTransform('article.xml','article.xslt');
              </xsl:attribute>
              <xsl:value-of select="msws:Title"/>
            </xsl:element>
          </li>
          <li>
            <xsl:call-template name="FormatDate">
              <xsl:with-param name="DateTimeParam" select="msws:PublishedDate" />
            </xsl:call-template>
          </li>
          <li>
            <xsl:value-of select="msws:Description"/>
          </li>

      </xsl:for-each>
    </ul>
</div>
  </xsl:template>

  <xsl:template name="FormatDate">
    <!-- expecting datetime example: 2009-04-20T00:00:00 -->
    <xsl:param name="DateTimeParam" />

    <!-- reformat date param to be easier to use -->
    <xsl:variable name="DateTime">
      <xsl:value-of select="substring($DateTimeParam,1,10)"/>
    </xsl:variable>

    <!-- new date format January 20, 2007 -->
    <xsl:variable name="year">
      <xsl:value-of select="substring-before($DateTime,'-')" />
    </xsl:variable>
    <xsl:variable name="mo-temp">
      <xsl:value-of select="substring-after($DateTime,'-')" />
    </xsl:variable>
    <xsl:variable name="mo">
      <xsl:value-of select="substring-before($mo-temp,'-')" />
    </xsl:variable>
    <xsl:variable name="day">
      <xsl:value-of select="substring-after($mo-temp,'-')" />
    </xsl:variable>

    <xsl:if test="(string-length($day) &lt; 2)">
      <xsl:value-of select="0"/>
    </xsl:if>
    <xsl:value-of select="$day"/>
    <xsl:value-of select="' '"/>
    <xsl:choose>
      <xsl:when test="$mo = '1' or $mo = '01'">Jan</xsl:when>
      <xsl:when test="$mo = '2' or $mo = '02'">Feb</xsl:when>
      <xsl:when test="$mo = '3' or $mo = '03'">Mar</xsl:when>
      <xsl:when test="$mo = '4' or $mo = '04'">Apr</xsl:when>
      <xsl:when test="$mo = '5' or $mo = '05'">May</xsl:when>
      <xsl:when test="$mo = '6' or $mo = '06'">Jun</xsl:when>
      <xsl:when test="$mo = '7' or $mo = '07'">Jul</xsl:when>
      <xsl:when test="$mo = '8' or $mo = '08'">Aug</xsl:when>
      <xsl:when test="$mo = '9' or $mo = '09'">Sep</xsl:when>
      <xsl:when test="$mo = '10'">Oct</xsl:when>
      <xsl:when test="$mo = '11'">Nov</xsl:when>
      <xsl:when test="$mo = '12'">Dec</xsl:when>
    </xsl:choose>
    <xsl:value-of select="' '"/>
    <xsl:value-of select="$year"/>
  </xsl:template>

</xsl:stylesheet>

Ответы [ 2 ]

2 голосов
/ 08 октября 2011

ОК - у вас проблема с пространством имен. Это результат преобразования content.xml с помощью content.xsl (отформатированного и сокращенного для удобства чтения) в качестве фрагмента документа DOM.

<?xml version="1.0" encoding="UTF-8"?>
<div 
    xmlns:msws="http://tempuri.org/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <ul id="categorybody">
        <li id="categoryitem">
            <a href="javascript:void(0)" onclick="
               XsltTransform(&apos;article.xml&apos;,&apos;article.xslt&apos;);
            ">The first title</a>
        </li>
        <li>07 Oct 2011</li>
        <li>A nice long description 1.</li>
        <li id="categoryitem">
        ... etc ... 
    </ul>
</div>

Следует отметить, что это фрагмент DOM на основе XML - и элементы находятся в без пространства имен . Поэтому, когда вы добавляете это напрямую в вашу DOM (как это сделано в вашем вопросе), Safari не будет рассматривать элементы как элементы HTML - потому что ожидает, что они находятся в пространстве имен http://www.w3.org/1999/xhtml.

Когда фрагмент сериализуется, он будет преобразован в XML выше.

Когда этот XML анализируется обратно с использованием innerHTML (как это делается в вашем исправленном рабочем коде), синтаксический анализатор будет обрабатывать XML как HTML. В соответствии с практикой парсинга HTML5 элементы будут автоматически помещены в пространство имен http://www.w3.org/1999/xhtml и будут обрабатываться как HTML, поэтому все будет работать так, как задумано.

Есть несколько проблем с вашим решением. Первая заключается в том, что сериализация в формате XML и синтаксический анализ в формате HTML рискованны. Например, элементы сценария могут быть сериализованы как <script src="..." />, что нормально для XML, но не для HTML.

Во-вторых, требуется цикл сериализации / разбора, который снижает производительность.

Чтобы решить эту проблему, достаточно добавить xmlns="http://www.w3.org/1999/xhtml" в качестве атрибута к элементу xsl:stylsheet content.xsl, но я не проверял это в Safari.

0 голосов
/ 08 октября 2011

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

main.xslt

<?xml version="1.0" encoding="iso-8859-1"?>

<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:msws="http://tempuri.org/"
    >

  <xsl:template match="/">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>main</title>
        <link href="StyleSheet1.css" rel="stylesheet" type="text/css" />
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
        <script type="text/javascript">
            function transform(xmlfile,xslfile)
            {
                var xmlRequest = new XMLHttpRequest();
                xmlRequest.open("GET", xmlfile, false);
                xmlRequest.send(null);
                xml= xmlRequest.responseXML;

                var xslRequest = new XMLHttpRequest();
                xslRequest.open("GET", xslfile, false);
                xslRequest.send(null);
                xsl = xslRequest.responseXML;

                xsltProcessor = new XSLTProcessor();
                xsltProcessor.importStylesheet(xsl);

                resultDocument = xsltProcessor.transformToFragment(xml,document);
                document.getElementById("contentbody").appendChild(resultDocument);
            }

            function go(xmlfile,xslfile)
            {
                var xmlRequest = new XMLHttpRequest();
                xmlRequest.open("GET", xmlfile, false);
                xmlRequest.send(null);
                xml= xmlRequest.responseXML;

                var xslRequest = new XMLHttpRequest();
                xslRequest.open("GET", xslfile, false);
                xslRequest.send(null);
                xsl = xslRequest.responseXML;
                xsltProcessor=new XSLTProcessor();
                xsltProcessor.importStylesheet(xsl);
                resultDocument = xsltProcessor.transformToFragment(xml,document);
                document.getElementById("contentbody").innerHTML = "";
                document.getElementById("contentbody").appendChild(resultDocument);
            }

            function loadXMLDoc(dname)
            {
                xhttp=new XMLHttpRequest();
                xhttp.open("GET",dname,false);
                xhttp.send("");
                return xhttp.responseXML;
            }

            function displayResult(xmlfile,xslfile)
            {
                xml=loadXMLDoc(xmlfile);
                xsl=loadXMLDoc(xslfile);
                xsltProcessor=new XSLTProcessor();
                xsltProcessor.importStylesheet(xsl);

var XmlDom = xsltProcessor.transformToDocument(xml);
var serializer = new XMLSerializer();
var output = serializer.serializeToString(XmlDom.documentElement);
//alert(output);
//              resultDocument = xsltProcessor.transformToFragment(xml,document);
                document.getElementById("contentbody").innerHTML = "";
//              document.getElementById("contentbody").appendChild(resultDocument);
document.getElementById("contentbody").innerHTML = output;
//              alert(document.getElementById("contentbody").innerHTML);
            }
        </script>
      </head>
      <body>
        <div id="main">
          <div id="menu">
            <div id="categorytitle">
              Categories
            </div>
            <ul id="categorybody">
              <xsl:for-each select="*/*/msws:FeedDTO">
                <xsl:if test="msws:Name != 'Free to view'">
                  <li id="menuitem">
                    <xsl:element name="a">
                      <xsl:attribute name="href">javascript:void(0)</xsl:attribute>
                      <xsl:attribute name="onclick">
                        displayResult('category.xml','category.xslt');
                      </xsl:attribute>
                      <xsl:value-of select="substring(msws:Name, 1, 100)"/>
                    </xsl:element>
                  </li>
                </xsl:if>
              </xsl:for-each>
            </ul>
          </div>
          <div id="content">
            <div id="contenttitle">
              Content
            </div>
            <div id="contentbody">
            <!--
              <div xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msws="http://tempuri.org/"><ul id="categorybody"><li id="categoryitem"><a href="javascript:void(0)" onclick="
                XsltTransform('article.xml','article.xslt');
              ">The first title</a></li><li>07 Oct 2011</li><li>A nice long description 1.</li><li id="categoryitem"><a href="javascript:void(0)" onclick="
                XsltTransform('article.xml','article.xslt');
              ">The second title</a></li><li>06 Oct 2011</li><li>A nice long description 2.</li><li id="categoryitem"><a href="javascript:void(0)" onclick="
                XsltTransform('article.xml','article.xslt');
              ">The third title</a></li><li>06 Oct 2011</li><li>A nice long description 3.</li><li id="categoryitem"><a href="javascript:void(0)" onclick="
                XsltTransform('article.xml','article.xslt');
              ">The fourth title</a></li><li>05 Oct 2011</li><li>A nice long description 4.</li><li id="categoryitem"><a href="javascript:void(0)" onclick="
                XsltTransform('article.xml','article.xslt');
              ">The fifth title</a></li><li>04 Oct 2011</li><li>A nice long description 5.</li></ul></div>-->
            </div>
          </div>
        </div>
      </body>
    </html>
  </xsl:template>

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