实体名称必须紧跟在实体引用中的“&”之后

IT技术 javascript xml jsf xhtml facelets
2021-01-29 19:45:19

我想在我的 *.xhtml 页面上放一个 packman 游戏。(我使用的是 jsf 2 和 primefaces 3.5)

然而,

当我在 xhtml 中“翻译”html 页面时,在此脚本中出现错误:

    <script>

    var el = document.getElementById("pacman");

    if (Modernizr.canvas && Modernizr.localstorage && 
        Modernizr.audio && (Modernizr.audio.ogg || Modernizr.audio.mp3)) {
      window.setTimeout(function () { PACMAN.init(el, "./"); }, 0);
    } else { 
      el.innerHTML = "Sorry, needs a decent browser<br /><small>" + 
        "(firefox 3.6+, Chrome 4+, Opera 10+ and Safari 4+)</small>";
    }
  </script>

在线:

if (Modernizr.canvas && Modernizr.localstorage && 

我得到:

实体名称必须紧跟在实体引用中的“&”之后。

知道如何解决这个问题吗?

6个回答

到目前为止发布的所有答案都提供了正确的解决方案,但是没有一个答案能够正确解释具体问题的根本原因。

Facelets 是一种基于 XML 的视图技术,它使用 XHTML+XML 生成 HTML 输出。XML 有五个特殊字符,它们被 XML 解析器特殊处理:

  • < 标签的开始。
  • > 标签的结尾。
  • " 属性值的开始和结束。
  • ' 属性值的替代开始和结束。
  • &实体的开头(以 结尾;)。

在箱子&,其后面没有#(例如&#160;&#xA0;等),XML解析器被隐含找五个一预定义的实体名称 ltgtampquotapos,或任何手动定义实体名称但是,在您的特定情况下,您使用的&是 JavaScript 运算符,而不是 XML 实体。这完全解释了您遇到的 XML 解析错误:

实体名称必须紧跟在实体引用中的“&”之后

本质上,您在错误的位置编写了 JavaScript 代码,即 XML 文档而不是 JS 文件,因此您应该相应地转义所有 XML 特殊字符。&必须进行转义为&amp;

因此,在您的特定情况下,

if (Modernizr.canvas && Modernizr.localstorage && 

必须成为

if (Modernizr.canvas &amp;&amp; Modernizr.localstorage &amp;&amp;

使其 XML 有效。

然而,这使得 JavaScript 代码更难阅读和维护。如果您想继续使用&而不是&amp;在 XML 文档中的 JavaScript 代码中使用,那么您应该将 JavaScript 代码放置在字符数据 (CDATA) 块中。因此,在 JSF 术语中,这将是:

<h:outputScript>
    <![CDATA[
        // ...
    ]]>
</h:outputScript>

XML 解析器将块的内容解释为“普通”字符数据而不是 XML,因此解释 XML 特殊字符“原样”。

但是,更好的是只是把自己的JS文件中的JS代码,您包括由<script src>,或者在JSF方面,<h:outputScript>

<h:outputScript name="onload.js" target="body" />

(注意target="body"; 这样 JSF 将<script>在 的最后自动呈现<body>,无论其<h:outputScript>自身位于何处,从而实现与window.onload相同的效果$(document).ready();因此您不再需要在该脚本中使用它们)

这样您就无需担心 JS 代码中的 XML 特殊字符。作为额外的好处,这让您有机会让浏览器缓存 JS 文件,从而使总响应大小更小。

也可以看看:

@Nacho321:仅当内容类型错误地设置为application/xhtml+xml而不是 时text/html,这反过来会导致某些浏览器(主要是 MSIE)出现多次故障。另请参阅“为 XHTML 编写 JavaScript”文档。在 JSF 中,如果您使用<f:view contentType="text/html">而不是让 JSF/webbrowser 自动猜测来完成工作,则不需要。另请参阅stackoverflow.com/tags/xhtml/info
2021-03-18 19:45:19
注意:这不仅发生在 Javascipt 操作中(因为我&amp;&amp;在 if 语句中正确使用了错误上方的一行),而且还发生在注释行上;我的错误出现了// TODO KevinC & Victor: some todo(现在它已更改为and..)。另外,非常感谢这篇文章。我之前遇到过它作为解决与 OP 相同的问题的方法。
2021-03-27 19:45:19
![CDATA[ 不应该是注释行吗?只是好奇。
2021-04-05 19:45:19
你的答案是错误的。它应该是 & 而不是 &&
2021-04-10 19:45:19
@funky-nd:我猜你把它和 &amp; 混淆了。现在考虑到这一点重新阅读答案。
2021-04-11 19:45:19

您需要在脚本标签内添加一个 CDATA 标签,除非您想手动通过并转义所有 XHTML 字符(例如&需要变成&amp;)。例如:

<script>
//<![CDATA[
var el = document.getElementById("pacman");

if (Modernizr.canvas && Modernizr.localstorage && 
    Modernizr.audio && (Modernizr.audio.ogg || Modernizr.audio.mp3)) {
  window.setTimeout(function () { PACMAN.init(el, "./"); }, 0);
} else { 
  el.innerHTML = "Sorry, needs a decent browser<br /><small>" + 
    "(firefox 3.6+, Chrome 4+, Opera 10+ and Safari 4+)</small>";
}
//]]>
</script>

解析器需要一些 HTML 内容,因此它认为&是实体的开头,例如&egrave;.

使用此解决方法:

<script type="text/javascript">
// <![CDATA[
Javascript code here
// ]]>
</script>

因此您指定代码不是 HTML 文本,而只是要按原样使用的数据。

<script>//<![CDATA[
    /* script */
//]]></script>

如果您使用 XHTML,出于某种原因,请注意XHTML 1.0 C 4说:“如果您的脚本使用 < 或 & 或 ]]> 或 --,请使用外部脚本。也就是说,不要将脚本代码嵌入script元素中,而是将其放入单独的 JavaScript 文件中并使用<script src="foo.js"></script>.