说服Firefox解析嵌入在XML中的HTML(在应用XSL之后)

时间:2010-07-16 21:02:21

标签: xml firefox xslt

我有一些这种形式的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来输出内容。输出值纯文本并尊重我的格式(来自CSS),复制输出纯文本并破坏我的格式(回退到正文格式,忽略div和表格)。

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

3 个答案:

答案 0 :(得分:1)

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

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

删除它们是安全的。

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

第三,移动XHTML名称空间声明

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

<xsl:stylesheet>元素并在其他地方删除它。

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

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

答案 1 :(得分:1)

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

当你说:

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

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

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

答案 2 :(得分:0)

您的XML输入确实嵌入了XHTML,因为这需要您希望被识别为XHTML的那些元素位于XHTML名称空间http://www.w3.org/1999/xhtml中。因此,您需要更改输入以将这些元素放在XHTML命名空间中,然后您可以简单地将它们在样式表中复制到结果树中,或者您需要更改样式表以将这些元素转换为XHTML命名空间中的元素。以下是这样做,也进行了一些其他更改,如设置版本=“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>