【问题标题】:XSTLProcessor bypass <tr> and <td> tagsXSTLProcessor 绕过 <tr> 和 <td> 标记
【发布时间】:2018-11-13 13:49:36
【问题描述】:

我在客户端中有一个 XML 和 XSL 文件,我想将其转换为 HTMLElement,以便我可以附加到当前元素

但结果与我的预期相差甚远。除了在 HtmlElement 结果中排除 &lt;td&gt;&lt;tr&gt; 标记之外,一切似乎都很好

我的 XML 文件

<?xml version="1.0" encoding="UTF-8"?>
<ns1:Courses xmlns:ns1="www.Course.com">
    <ns1:Course xmlns:ns1="www.Course.com">
        <ns1:Id>2153</ns1:Id>
        <ns1:Name>7 bước làm sao tận hưởng một chuyến du lịch nước ngoài với chi phí thấp</ns1:Name>
        <ns1:Author>Hoàng Lê Giang</ns1:Author>
        <ns1:AuthorImageURL>
            d1nzpkv5wwh1xf.cloudfront.net/320/k-57b67d6f60af25054a055b25/20170928-gianghl_2809/gianghl01.jpg
        </ns1:AuthorImageURL>
        <ns1:Rating>0.0</ns1:Rating>
        <ns1:RatingNumber>0</ns1:RatingNumber>
        <ns1:Cost>599000.0</ns1:Cost>
    </ns1:Course>

我的 XSL 文件

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html" encoding="UTF-8" indent="yes" media-type="text/html"/>
    <xsl:template match="/">

        <xsl:for-each select="//*[local-name()='Course']">
            <tr>
                <td class="col1">
                    <div class="course_name">
                        <a href="{*[local-name()='SourceURL']}">
                            <xsl:value-of select="*[local-name()='Name']"/>
                        </a>

                    </div>
                    <div class="course_small_detail">

                        <img class="img_author_small"
                             src="{*[local-name()='AuthorImageURL']}"/>
                        <span class="author_name">
                            <xsl:value-of select="*[local-name()='Author']"/>
                        </span>

                    </div>


                </td>

                <td class="col2">
                    <xsl:value-of select="*[local-name()='Cost']"/>
                </td>
                <td class="col3">
                    <xsl:value-of select="*[local-name()='Rating']"/>
                </td>
            </tr>
        </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

我用于转换和附加结果的 javascript 代码

var xmlDoc = xmlHttp.responseXML;
            var xslDoc = xslHttp.responseXML;

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

            //used to add to html document
            var resultDocument = xsltProcessor.transformToFragment(xmlDoc, document);
            console.log(resultDocument);
            document.getElementById("xmlResult").appendChild(resultDocument);

我的 html 结果渲染

 <table class="table_result">
                    <thead>
                    <tr>
                        <th>header1 </th>

                        <th>header2 </th>
                        <th>header3 </th>
                    </tr>
                    </thead>
                    <tbody id="xmlResult">
                    </tbody>
</table>

我相信这是因为我用来转换的 XSLTProcessor,因为我尝试使用我的 IDE 的 XSLT 工具对其进行转换,结果完全正确

【问题讨论】:

  • 特定浏览器或所有支持 XSLTProcessor 的浏览器是否都会出现该问题?你能把问题降到最低,并将其作为可执行代码sn-p插入吗?您是否尝试过让 XSLT 创建一个完整的 HTML table,然后使用 Javascript 将现有表替换为 XSLT 执行的结果片段?
  • 我目前不确定是什么导致了问题,但我猜是由于浏览器使用 XSLT 的方式不同(即 Firefox 进行节点到节点转换,Chrome 使用 libxslt 进行序列化/解析并可能再次序列化)尝试创建tr 元素的序列是自找麻烦。
  • 我尝试了不同的浏览器,结果还是一样的遗憾:(
  • 我尝试了一个示例 jsfiddle.net/bycptmL2/3,它适用于我的 Firefox,而不是 Chrome。正如我所说,虽然两者都具有与 XSLTProcessor 和 transformToFragment 相同的 API,但我认为它们的实现方法,更不用说,它们将 XSLT 集成到浏览器中的整个架构,据我所知,差别很大,所以整个想法让 XSLT 返回一个片段,其中包含要插入到 tbody 的 HTML tr 元素是很麻烦的。
  • 另一方面,jsfiddle.net/bycptmL2/4 仅将 XSLT 更改为输出 XHTML tr 元素节点,对我来说适用于 Firefox 和 Chrome。不确定 Edge,似乎根本无法使用那个小提琴。

标签: javascript html xml xslt transformation


【解决方案1】:

在 Windows 10 1803 上使用当前版本的 Firefox、Chrome 和 Edge,我可以让 XSLT 返回带有 XHTML tr 元素的片段,然后将其插入到托管 HTML 文档和 tbody

var domParser = new DOMParser();

var xmlString = `<root>
  <item>
    <value>foo 1<\/value>
    <value>foo 2<\/value>
    <value>foo 3<\/value>
  <\/item>
  <item>    
    <value>bar 1<\/value>
    <value>bar 2<\/value>
    <value>bar 3<\/value>
  <\/item>
<\/root>`;

var xslString = `<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns="http://www.w3.org/1999/xhtml">
  <xsl:output method="xml" indent="yes"/>
  
  <xsl:template match="item">
    <tr>
      <xsl:apply-templates/>
   <\/tr>
 <\/xsl:template>
 
 <xsl:template match="value">
   <td>
     <xsl:apply-templates/>
   <\/td>
 <\/xsl:template>
 
<\/xsl:stylesheet>`;

var xmlInputDoc = domParser.parseFromString(xmlString, 'application/xml');

var xsltDoc = domParser.parseFromString(xslString, 'application/xml');

var xsltProc = new XSLTProcessor();
xsltProc.importStylesheet(xsltDoc);

var fragment = xsltProc.transformToFragment(xmlInputDoc, document);

console.log(fragment);

var table = document.getElementById('table1');

var tBody = document.getElementById('xmlResult');

tBody.appendChild(fragment);
<table id="table1" class="table_result">
                    <thead>
                    <tr>
                        <th>header1 </th>

                        <th>header2 </th>
                        <th>header3 </th>
                    </tr>
                    </thead>
                    <tbody id="xmlResult">
                    </tbody>
</table>

【讨论】:

  • 如果在 中设置 method='html' 会发生什么?
  • @Ziggy192,好吧,试试自己,部分(方法html)我在jsfiddle.net/bycptmL2/3中尝试过(我没有在那里使用XHTML命名空间,因为这似乎没有意义与 XSLT 1 中的输出方法 html 一起使用,并且正如前面在评论中指出的那样,该小提琴在 Chrome 中无法正常工作。
  • 谢谢@Martin!它适用于 XHTML 名称空间和 XML 方法。没有文件提到我的案子。我应该认为这是 XSTLProcessor 的错误,还是我的方法从一开始就有问题?再次感谢您的帮助,非常感谢
  • XSLTProcessor 没有详细的规范,它只是 Mozilla 在尝试将自己的 XSLT 1.0 实现集成到浏览器时引入的一个 API。其他遵循 API,以确保 API 级别的兼容性,但据我了解,由于 XSLT 集成的体系结构差异太大,更精细级别的兼容性从未奏效。
  • 如果您查看jsfiddle.net/bycptmL2/5,其中没有使用 XSLT,但只是将一系列 tr 元素解析为 HTML,您会看到 trtd 元素也被删除了,所以没有任何 HTML 的 sn-p 可以很好地作为独立的片段。也就是说,正如我猜想的那样,这里的主要问题是,使用您的原始方法,Chrome 等浏览器将 XSLT 的结果作为字符串并将其提供给 HTML 解析器,该解析器会丢弃上下文之外的 tr/td 元素。如果您切换到输出方法 xml 并使用 XHTML 命名空间,那么您在放置元素之间没有 HTML 解析器。
猜你喜欢
  • 2013-03-23
  • 2015-02-11
  • 1970-01-01
  • 1970-01-01
  • 2012-10-30
  • 1970-01-01
  • 2011-04-30
  • 1970-01-01
  • 2015-04-12
相关资源
最近更新 更多