实体名称必须紧随实体参考中的“&”


91

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

我得到:

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

任何想法如何解决?

Answers:


219

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

Facelets是基于XML的视图技术,它使用XHTML + XML生成HTML输出。XML具有五个特殊字符,XML解析器对其进行了特殊处理:

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

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

实体名称必须紧随实体参考中的“&”

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

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

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

必须成为

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

使它对XML有效。

但是,这使JavaScript代码更难以阅读和维护。如Mozilla开发人员网络出色的文档“为XHTML编写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文件,从而减小总响应大小。

也可以看看:


![CDATA [不应该是注释行吗?只是好奇。
Nacho321

@ Nacho321:仅当内容类型错误地设置为application/xhtml+xml而不是时text/html,这反过来会导致某些浏览器(主要是MSIE)出现多个故障。另请参见“为XHTML编写JavaScript”文档。在JSF中,不需要使用<f:view contentType="text/html">而不是让JSF / webbrowser自动猜测来完成工作。另请参见stackoverflow.com/tags/xhtml/info
BalusC 2013年

注意:这不仅发生在Javascipt操作中(因为我&amp;&amp;在错误上方的if语句中正确使用了if语句),而且在注释行中也是如此;我的错误发生了// TODO KevinC & Victor: some todo(现在它已更改为and..)。另外,非常感谢这篇文章。我之前遇到过它,是为了解决与OP相同的问题。
凯文·克鲁伊森

你的答案是错误的。应该是&amp; 代替&amp;&amp;
时髦的

1
@ funky-nd:我想您将它与&amp; amp;混淆了。现在,请牢记这一点,重新阅读答案。
BalusC

14

您需要在script标签内添加一个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>

12

解析器期望一些HTML内容,因此它将&视为实体的开始,例如&egrave;

使用以下解决方法:

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

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



2

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


0

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.