代码之家  ›  专栏  ›  技术社区  ›  ssube

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

  •  1
  • ssube  · 技术社区  · 14 年前

    <?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,因为Firefox没有解析任何嵌入的XHTML。在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>
    

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

    而且,我两个都试过了xsl:value-of and xsl:copy-of to 输出内容。值输出纯文本并尊重我的格式(来自CSS),副本输出纯文本并破坏我的格式(返回到正文格式,忽略div和table)。

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

    3 回复  |  直到 7 年前
        1
  •  1
  •   Mads Hansen    14 年前

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

    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">
    
        2
  •  1
  •   user357812 user357812    14 年前

    第一:我正在用firefox3.5.9运行这个程序。这没有问题,但那是错误的。

    当你说:

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

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

    :MSXSL正确添加 xmlns=“” 声明 Body

        3
  •  0
  •   Martin Honnen    14 年前

    您的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>