【问题标题】:How can you deal with embedded XML tags in XSLT?如何处理 XSLT 中嵌入的 XML 标记?
【发布时间】:2011-06-10 02:30:20
【问题描述】:

我正在使用 XSLT 将 XML 转换为 HTML。我无法弄清楚如何处理嵌入的 XML 节点以进行格式化。例如,假设我有 XML 元素:

<favoriteMovie>the <i>Star Wars</i> saga</favoriteMovie>

但是,在 XLST 期间,<i> 标记被忽略,因此 HTML 输出中的“星球大战”不是斜体。有没有相对简单的方法来解决这个问题?

test.xml:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="test.html.xsl"?>
<favoriteMovies>
    <favoriteMovie>the <i>Star Wars</i> saga</favoriteMovie>
</favoriteMovies>

test.html.xsl:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" omit-xml-declaration="yes" />
    <xsl:template match="/">
      <html>
        <head />
          <body>
            <ul>
                <xsl:for-each select="favoriteMovies/favoriteMovie">
                    <li><xsl:value-of select="." /></li>
                </xsl:for-each>
            </ul>
          </body>
      </html>
    </xsl:template>
</xsl:stylesheet>

【问题讨论】:

  • 好问题,+1。有关问题原因的解释以及两个完整而简短的解决方案,请参阅我的答案。请注意,当前接受的答案是完全错误的。将标记放入 CDATA 部分会将其转换为不可用的一维文本,通常被认为是一种不好的做法。
  • @Dimitre Novatchev,除非绝对没有必要将该 html 视为结构化的,并且其唯一目的是按原样传递给浏览器,而不会使用任意 html 破坏原始 XML 结构标签。
  • 在相互判断之前,让我们先了解一下。请详细说明“被破坏的标记”,我没有关注你。
  • @etranger:你可以很容易地找到为什么破坏标记是不好的做法——只需搜索。您可以从以下内容开始:xml.silmaril.ie/cdata.html,但您可以轻松找到许多其他来源。
  • 这里的代码pastie.org/1468206 产生了这个输出dl.dropbox.com/u/16517379/xslt-ss.png,我似乎无法理解为什么标记被“破坏”了。本质上:提供的解决方案有效,最初由 OP 标记为有效。我也有我的论据。让我们谈谈并清除它。

标签: html xml xslt formatting


【解决方案1】:

您应该使用“禁用输出转义”属性。 element的一般格式为:

<xsl:value-of select="expression" disable-output-escaping="yes|no" />

'disable-output-escaping' 是可选的。 “yes”表示特殊字符(如“

因此只需将您的代码更改为:

<xsl:template match="favoriteMovie">
  <xsl:copy-of select="node()" disable-output-escaping="yes"/>
</xsl:template>

【讨论】:

  • 为什么我得到'disable-output-escaping' is an invalid attribute for the 'xsl:copy-of' element.
  • disable-output-escaping 并未得到普遍支持,不鼓励使用。见stackoverflow.com/a/701793/130121
【解决方案2】:

有两点需要注意。

首先。确保在 CDATA 中筛选标签

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="test.html.xsl"?>
<favoriteMovies>
    <favoriteMovie><![CDATA[the <i>Star Wars</i> saga]]></favoriteMovie>
</favoriteMovies>

第二。禁用输出转义:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes" />
<xsl:template match="/">
  <html>
    <head />
      <body>
        <ul>
            <xsl:for-each select="favoriteMovies/favoriteMovie">
                <li><xsl:value-of select="." disable-output-escaping="yes" /></li>
            </xsl:for-each>
        </ul>
      </body>
  </html>
</xsl:template>

编辑:使用编辑器管理它,现在代码显示为应有的样子

EDIT2:在您的代码中包含更改

EDIT3:对于谁可能关心的问题,问题的真正领域是关于结构化电影信息,而不是 html 数据。 HTML 仅用于标记目的,假设在 favoriteMovie 中有 html 标题标签,而同名标签标题可能是 movies 数据库中的有效标签。这些标题的明确必须有不同的解释。这证明使用 CDATA 然后在处理时禁用输出是合理的。

【讨论】:

  • 1.没有按预期工作; HTML 最终看起来像:<i>星球大战</i>传奇
  • 使用 gt 和 lt 实体是我试图解决编辑器问题的尝试,不要在文档中使用它们。重点是使用 CDATA 将 HTML 标签包装在 XML 标签内。
  • 2.似乎没有任何改变,标签仍然被忽略
  • 我试过 1. 用 ,而不是 <i>但它没有按预期工作。它显示在原始 HTML 中,就像我在之前的评论中指定的那样,在渲染的 HTML 中显示为“Star Wars saga”,这显然不是我想要的。
  • Re: EDIT 3 - 你似乎试图回答一个他没有问过的问题。
【解决方案3】:

但是,在 XLST 期间,&lt;i&gt; 标记获取 被忽略了,所以“星球大战”不是 在 HTML 输出中斜体。是 有一个相对简单的方法来解决 这个?

你的问题在这里

<ul>
  <xsl:for-each select="favoriteMovies/favoriteMovie">
    <li><xsl:value-of select="."/></li>
  </xsl:for-each>
</ul>

&lt;xsl:value-of&gt; 指令用于创建文本节点。这样做时,它将在此 XSLT 指令的 select 属性中指定的 XPath 表达式的字符串值复制到输出。元素的字符串值是其所有文本节点后代的串联。

这就是您获得报告输出的方式。

解决方案

使用&lt;xsl:copy-of&gt; 指令,该指令复制其select 属性中指定的所有节点:

<ul>
  <xsl:for-each select="favoriteMovies/favoriteMovie">
    <li><xsl:copy-of select="node()"/></li>
  </xsl:for-each>
</ul>

另一个更符合 XSLT 原则的解决方案完全避免使用&lt;xsl:for-each&gt;

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <html>
    <head />
    <body>
     <xsl:apply-templates/>
    </body>
  </html>
 </xsl:template>

 <xsl:template match="/*">
  <ul>
   <xsl:apply-templates/>
  </ul>
 </xsl:template>

 <xsl:template match="favoriteMovie">
  <li><xsl:copy-of select="node()"/></li>
 </xsl:template>
</xsl:stylesheet>

当上面定义的两种解决方案中的任何一种应用于提供的 XML 文档时

<favoriteMovies>
    <favoriteMovie>the 
        <i>Star Wars</i> saga
    </favoriteMovie>
</favoriteMovies>

产生想要的正确结果

<html>
    <head/>
    <body>
        <ul>
            <li>the 
                <i>Star Wars</i> saga
            </li>
        </ul>
    </body>
</html>

【讨论】:

  • 我更喜欢这个答案,因为它更简单并且可以在不破坏我的纯文本 XSLT 的情况下工作。谢谢!
  • @James-Walford:您的回答存在一个问题:您无法提前知道favoriteMovie 中的 html 元素是什么,因此提供与任何可能的 html 元素匹配的单独模板是不现实的。如果你真的想避免使用xsl:copy-of,你需要使用身份规则。我没有提供身份规则的解决方案,因为这与最初的问题相去甚远。
  • 我应该能够解决这个问题,但是如果我想做同样的事情并且我总是有一个节点而不是多个节点,那么 XSL 语法会是什么样子?我尝试将 更改为 ,但随后 标记出现在原始 HTML 中并且它不呈现正确。
  • @Dimitre Novatchev 谢谢 - 好点,我的回答是基于它只是 i 元素。
  • 知道了:
【解决方案4】:

你应该使用 xsl:copy 来复制 i 节点。

http://msdn.microsoft.com/en-us/library/ms256128.aspx

    <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" omit-xml-declaration="yes" />
    <xsl:template match="/">
      <html>
        <head />
          <body>
            <xsl:apply-templates></xsl:apply-templates>        
          </body>
      </html>
    </xsl:template>
<xsl:template match="favoriteMovies">
  <ul>
    <xsl:apply-templates></xsl:apply-templates>
  </ul>  
</xsl:template>
  <xsl:template match="favoriteMovie">
    <li>      
      <xsl:apply-templates></xsl:apply-templates>
    </li>
  </xsl:template>
  <xsl:template match="i">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

【讨论】:

  • 这通常是错误的做法,因为 不是来自源 XML 命名空间,而是来自 HTML 命名空间,应该这样对待,或者根本不作为标签因此作为 CDATA 的一部分。
  • 没有迹象表明他的 XML 中有任何命名空间引用,并且他无论如何都在尝试输出 html。他的输入不包括 CDATA,因此告诉他如果包含 CDATA 应该如何处理似乎没有什么意义。
  • 关键是,他的代码可以包含任何html标签,包括格式错误的文本等,不应该像对待源xml一样对待它。请理解我的想法,这不是关于正式的命名空间,而是使用 作为结构和 作为标记 的逻辑范围
  • 据我所知,您的评论与原始 XML 的构造更相关。如果它包含不在 CDATA 中的未封闭的 HTML 元素,那么它无论如何都不会形成良好的格式。如果他的 XML 格式正确,但恰好包含一些 HTML 元素,没有明确的命名空间,那么仅仅将它们复制出来是没有问题的。
猜你喜欢
  • 2019-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-18
  • 1970-01-01
  • 1970-01-01
  • 2012-11-29
相关资源
最近更新 更多