105

我想在我的 *.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 && 

我得到:

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

知道如何解决吗?

4

6 回答 6

247

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

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

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

如果&后面没有#(例如&#160;&#xA0;等),则 XML 解析器会隐式查找五个预定义的实体名称 ltgt、和之一amp,或任何手动定义的实体名称。但是,在您的特定情况下,您使用的是 JavaScript 运算符,而不是 XML 实体。这完全解释了您遇到的 XML 解析错误:quotapos&

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

本质上,您在错误的位置编写了 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>使用<h:outputScript>.

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

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

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

也可以看看:

于 2013-05-02T01:05:01.783 回答
16

您需要在脚本标记内添加一个 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>
于 2013-04-30T15:43:50.610 回答
13

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

使用此解决方法:

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

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

于 2013-04-30T15:44:03.783 回答
5

<script>//<![CDATA[
    /* script */
//]]></script>
于 2013-04-30T15:44:41.517 回答
2

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

于 2013-04-30T17:08:10.830 回答
0

以防万一有人从 Blogger 到达,我Beautify在 VSCode 中使用扩展时遇到了这个问题。不要使用它,不要beautify它。

于 2020-10-11T17:02:42.227 回答