【问题标题】:Convince Firefox to parse HTML embedded in XML (after XSL is applied)说服 Firefox 解析嵌入在 XML 中的 HTML(在应用 XSL 之后)
【发布时间】:2011-03-17 04:17:06
【问题描述】:

我有一些这种形式的 XML 文件:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="biomirror.xsl"?>
<Thread>
    <Title> Some thread title </Title>
    <Posts>
        <Post>
            <Author> Me </Author>
            <Body>
                This is the post body, which <b>may</b> have embedded XHTML, including all sorts of things like:<br />
                <div class="quote">Quotes</div>
                I know it's XHTML, though, the program spitting out XML verifies that.
            </Body>
        </Post>
    </Posts>
</Thread>

我需要将它们格式化为可读的线程,因此我使用了 CSS 样式表和 XSL 样式表。 CSS 有效,我知道事实上这并没有错。我的问题似乎出在 XSL 上,因为任何嵌入式 XHTML 都没有被 Firefox 解析。在 IE 中它可以完美运行并且格式正确,但在 Firefox 中它完全是纯文本。我认为这与它在输出之前被转义有关,但我不知道如何防止这种情况发生。

XSL 是:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output 
  omit-xml-declaration="yes" 
  method="xml" 
  media-type="application/xhtml+xml" 
  indent="no" 
  doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
/>
<xsl:template match="Posts">
<xsl:for-each select="Post">
    <tr xmlns="http://www.w3.org/1999/xhtml" class="Post">
      <td>
        <div>
          <table width="100%" cellpadding="0" cellspacing="0">
            <tr>
              <td class="Author">
                <xsl:value-of select="Author"/>
              </td>
              <td class="Date">
                Post <xsl:value-of select="PostID"/> 
                <xsl:choose>
                  <xsl:when test="count(LastPost) > 0">
                    (lastpost)
                  </xsl:when>
                </xsl:choose> at <xsl:value-of select="Date"/>
              </td>
            </tr>
          </table>
        </div>
        <div class="Body">
           <xsl:copy-of select="Body" />
        </div>
        <xsl:choose>
          <xsl:when test="count(Sig) = 1">
            <div class="Sig">
              <xsl:value-of disable-output-escaping="yes" select="Sig"/>
            </div>
          </xsl:when>
          <xsl:when test="count(Sig) = 0">
            <div class="SigFooter"> </div>
          </xsl:when>
        </xsl:choose>
      </td>
    </tr>
</xsl:for-each>
</xsl:template>

<xsl:template match="Thread">
  <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <xsl:choose>
          <xsl:when test="count(Title) = 1">
            <title>
              <xsl:value-of select="Title"/>
            </title>
          </xsl:when>
        </xsl:choose>
        <link href="resources/main.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
      <table class="Thread" align="center" width="90%" height="95%" cellpadding="2em">
        <tr>
          <td colspan="3">
            <div class="Title">
          <xsl:value-of select="Title"/>
              <br />
              <a href="whatis.xml">
                <img src="resources/banner.png" />
              </a>
            </div>
          </td>
        </tr>
        <xsl:apply-templates select="Posts"/>
        <tr height="100%">
         <td valign="bottom">
       <div class="Footer">
             Footer message n stuff
           </div>
         </td>
        </tr>
      </table>
    </body>
  </html>
</xsl:template>

我将其归咎于 Visual Studio,这有点骇人听闻。这是我第一次弄乱 XSL(虽然对 XML 比较熟悉),所以我还没有最模糊的方法来解决这个问题。 :)

现在,我读到了这个问题: XSLT: Parsing HTML embedded in XML? 并尝试将其集成到我的 XML 和 XSL 中(如上所示)。但在 Firefox 中仍然无法使用。

编辑:另外,我尝试了 xsl:value-of 和 xsl:copy-of 来输出内容。 Value-of 输出纯文本并尊重我的格式(来自 CSS),copy-of 输出纯文本并破坏我的格式(退回到正文格式,忽略 div 和表格)。

Edit2: 修订 XSL 以反映来自答案的建议。格式很好,但嵌入的标签仍然以文本形式出现,而不是被解释。

【问题讨论】:

    标签: xml firefox xslt


    【解决方案1】:

    首先,您不需要这些声明:

    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
    

    删除它们是安全的。

    其次,您永远不需要提及child:: 轴。这在 XSLT 中是隐含的,只需将其踢掉,无需替换。

    三、移动XHTML命名空间声明

    xmlns="http://www.w3.org/1999/xhtml"
    

    到&lt;xsl:stylesheet&gt; 元素并将其删除到其他任何地方。

    最后但同样重要的是:您是否尝试过正确的 XHTML 输出方法和媒体类型?

    <xsl:output method="xml" media-type="application/xhtml+xml">
    

    【讨论】:

    • 哦,还有:CSS 在标准渲染模式下区分大小写。只需仔细检查您的班级名称是否正确。
    • 我的班级名称是正确的,看起来像。我刚刚尝试了你所有的建议。它解决了复制到忽略样式的问题,但在页面周围引入了一个细白边框,仍然没有解决 XHTML 不被解释为这样的问题。
    • @peachy:这些只是建议。你做客户端 XSLT 处理?
    • 我想是的。就像我说的,我不熟悉 XSLT。我有 XML 页面,包括 xml 样式表。那些在浏览器中打开,据我所知,由浏览器来转换它。因此,为什么它在 IE 中有效,但在 Firefox 中无效。我可以在服务器端做,但我不知道有多少页面或它们会有什么内容,或者它们什么时候会更新。
    【解决方案2】:

    首先:我在 Firefox 3.5.9 上运行它。它没有问题,但这是错误的。

    当你说:

    <xsl:copy-of select="child::Body" /> 
    

    您正在处理一个非命名空间元素及其内容。而且因为您没有使用 XHTML 名称空间声明此内容,所以这些不是 XHTML 元素。他们应该有一个xmlns="" 声明。但是我的 Firefox 版本做错了:没有将命名空间元素(例如 b)解释为 XHTML 元素(没有空的命名空间!)。因为您没有提供 CSS 样式表,所以我无法进行 CSS 测试(如果没有命名空间元素获取样式)。

    编辑:MSXSL 在Body 中正确添加了xmlns="" 声明,但随后IE 呈现MS 想要的任何内容。贾!

    【讨论】:

    • 我刚刚编辑了帖子以反映其他答案的建议。样式很好,我认为所有样式表问题都已修复。无论哪种方式,我都可以自己调试 CSS 没问题,我只是不熟悉 XSL。我删除了 child:: 部分。但是,在 Firefox 3.6.6 中它不起作用。用 XHTML 命名空间声明内容是什么意思?
    • @peachykeen:您需要将默认命名空间声明添加到输入中的Body 元素中,如xmlns="http://www.w3.org/1999/xhtml",还要在样式表中定义该命名空间的前缀为xmlns:xhtml="http://www.w3.org/1999/xhtml",然后选择@ 987654329@ 元素内容与xhtml:Body/node() xpath。
    • 刚刚试过,FF 3.6.6 中的嵌入式 XHTML 仍然没有解析。不过,如果我误解了你,我会继续努力。
    • @Alejandro:我尝试更多地使用它,并且能够使用您的示例检索节点。然而,在我的 FF 上,它并不能解决这个问题,而且实际上在 IE 上也打破了它。我不确定为什么我们会得到如此不同的结果。您是否有机会编辑您的答案以包含您建议的代码,以确保我理解正确?
    【解决方案3】:

    您的 XML 输入没有嵌入了 XHTML,因为这需要您希望被识别为 XHTML 的元素位于 XHTML 命名空间 http://www.w3.org/1999/xhtml 中。因此,您要么需要更改输入以将这些元素放在 XHTML 命名空间中,然后您确实可以简单地将它们在样式表中复制到结果树,或者您需要更改样式表以将这些元素转换为 XHTML 命名空间中的元素。以下是这样做的,还进行了一些其他更改,例如设置 version="1.0":

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output 
      omit-xml-declaration="yes" 
      method="xml" 
      media-type="application/xhtml+xml" 
      indent="no" 
      doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
    />
    <xsl:template match="Posts">
    <xsl:for-each select="Post">
        <tr class="Post">
          <td>
            <div>
              <table width="100%" cellpadding="0" cellspacing="0">
                <tr>
                  <td class="Author">
                    <xsl:value-of select="Author"/>
                  </td>
                  <td class="Date">
                    Post <xsl:value-of select="PostID"/> 
                    <xsl:choose>
                      <xsl:when test="count(LastPost) > 0">
                        (lastpost)
                      </xsl:when>
                    </xsl:choose> at <xsl:value-of select="Date"/>
                  </td>
                </tr>
              </table>
            </div>
            <div class="Body">
               <xsl:apply-templates mode="to-xhtml" />
            </div>
            <xsl:choose>
              <xsl:when test="count(Sig) = 1">
                <div class="Sig">
                  <xsl:value-of disable-output-escaping="yes" select="Sig"/>
                </div>
              </xsl:when>
              <xsl:when test="count(Sig) = 0">
                <div class="SigFooter"> </div>
              </xsl:when>
            </xsl:choose>
          </td>
        </tr>
    </xsl:for-each>
    </xsl:template>
    
    <xsl:template match="Thread">
      <html>
        <head>
            <xsl:choose>
              <xsl:when test="count(Title) = 1">
                <title>
                  <xsl:value-of select="Title"/>
                </title>
              </xsl:when>
            </xsl:choose>
            <link href="resources/main.css" rel="stylesheet" type="text/css" />
        </head>
        <body>
          <table class="Thread" align="center" width="90%" height="95%" cellpadding="2em">
            <tr>
              <td colspan="3">
                <div class="Title">
              <xsl:value-of select="Title"/>
                  <br />
                  <a href="whatis.xml">
                    <img src="resources/banner.png" />
                  </a>
                </div>
              </td>
            </tr>
            <xsl:apply-templates select="Posts"/>
            <tr height="100%">
             <td valign="bottom">
           <div class="Footer">
                 Footer message n stuff
               </div>
             </td>
            </tr>
          </table>
        </body>
      </html>
     </xsl:template>
    
      <xsl:template match="*" mode="to-xhtml">
        <xsl:element name="{local-name()}">
          <xsl:apply-templates select="@* | node()" mode="to-xhtml"/>
        </xsl:element>
      </xsl:template>
    
      <xsl:template match="@* | text() | processing-instruction() | comment()" mode="to-xhtml">
        <xsl:copy/>
      </xsl:template>
    
    </xsl:stylesheet>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-03
      • 1970-01-01
      • 2012-11-18
      • 2018-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多