XHTML5和HTML4字符实体

11

XHTML5是否支持字符实体,例如 —?在工作中,我们可能需要特定的软件才能访问网站的管理员界面,人们要求多文件上传。对我来说,这是一个很容易的理由,要求迁移到FF 3.6+,所以我很快就会这样做。我们目前使用的是XHTML 1.1,在转换到HTML5时,我仅遇到了字符实体名称的问题...有没有人有相关文档呢?

我看到WHATWG规范中有一个列表,但我不确定它是否影响作为application/xhtml+xml提供的文件。无论如何,这两个实体名称都会在Chromium nightly和FF 3.6中触发错误。

5个回答

13

XHTML5没有DTD,因此XML解析器将不会看到实体定义(除了预定义的实体)。如果要使用实体,您需要在内部子集中自己定义它。

<!DOCTYPE html [
    <!ENTITY mdash "—">
]>
<html xmlns="http://www.w3.org/1999/xhtml">
    ... &mdash; ...
</html>

当然,如果您将内部子集作为text/html提供给浏览器使用,很可能会使其出现问题。在非XHTML HTML5文档中发送内部子集是不允许的。

HTML5维基目前建议:

不要在XHTML中使用实体引用(除了5个预定义实体:&amp;&lt;&gt;&quot;&apos;

我赞同这个建议,不仅适用于XHTML5,还适用于XML和HTML的一般情况。今天几乎没有理由再使用HTML实体。直接输入Unicode字符对每个人来说都更容易阅读,而&#...;字符引用可用于那些不能保证8位编码/清洁传输的悲惨情况。(由于大多数Unicode字符未定义HTML实体,因此您仍然需要它们。)


5
如果你想要更易读的文本,只需输入一个“-”字符即可。试图学习所有HTML实体名称是没有用的。使用真实的字符;如果必要,可以从字符映射中粘贴它,但是如果你经常这样做,有更简单的输入这些字符的方法。(例如,在我的键盘上,按住shift和alt键再按减号即可输入该字符。) - bobince
1
我点赞了那条评论,因为它是正确的,但是" "怎么比&#xa0;更不可读呢? - Evan Carroll
2
这就是为什么大多数XML用户今天不使用实体引用的原因。这里有一个更易读的不间断空格:‘ ’。(顺便说一下,这在我的键盘上是Shift + Space!) - bobince
5
很遗憾,从视觉上看,读原始资料的人并没有看到任何不同。 - Evan Carroll
1
@bobince: 关于“XHTML5没有DTD”的问题,我认为你的答案可能需要更新。在W3C HTML5推荐规范的第9.2节“解析XHTML文档”中(http://www.w3.org/TR/html5/the-xhtml-syntax.html#parsing-xhtml-documents),指出:“本规范提供了以下额外信息,用户代理在检索外部实体时应使用:...(此URL是包含所列名称的命名字符引用的实体声明的DTD)。 - DavidRR
显示剩余2条评论

6

我需要对可能是HTML 5的XML进行验证。HTML 4和XHTML只有大约250个实体,而当前的草案(2012年1月)有2000多个。

GET 'http://www.w3.org/TR/html5-author/named-character-references.html' |
xmllint --html --xmlout --format --noent - | 
egrep '<code|<span.*glyph' |  # get only the bits we're interested in
sed -e 's/.*">/__/' | # Add some "__" markers to make e.g. whitespace
sed -e 's/<.*/__/' |  #  entities work with xargs
sed 's/"/\&quot;/' | # xmllint output contains " which messes up xargs
sed "s/'/\&apos;/" | # ditto apostrophes. Make them HTML entities instead.
xargs -n 2 echo |  # Put the entity names and values on one line
sed 's/__/<!ENTITY /' | # Make a DTD
sed 's/;__/ /' |
sed 's/ __/"/'  |
sed 's/__$/">/' |
egrep -v '\bapos\b|\bquot\b|\blt\b|\bgt\b|\bamp\b' # remove XML entities.

您最终得到的是一个包含2114个实体的文件。
<!ENTITY AElig "&#xC6;">
<!ENTITY Aacute "&#xC1;">
<!ENTITY Abreve "&#x102;">
<!ENTITY Acirc "&#xC2;">
<!ENTITY Acy "&#x410;">
<!ENTITY Afr "&#x1D504;">

将此内容插入XML解析器中,应该允许XML解析器解析这些字符实体。
更新于2012年10月:由于工作草案现在有一个JSON文件(是的,我仍然在使用正则表达式),我将其简化为一个单独的sed命令。
curl -s 'http://www.w3.org/TR/html5-author/entities.json' |
sed -n '/^  "&/s/"&\([^;"]*\)[^0-9]*\[\([0-9]*\)\].*/<!ENTITY \1 "\&#\2;">/p' |
uniq

当然,使用JavaScript编写等价代码会更加强大,但并非每个人都安装了node。而sed是几乎所有人都有的工具,对吧?随机样本输出:
<!ENTITY subsetneqq "&#10955;">
<!ENTITY subsim "&#10951;">
<!ENTITY subsub "&#10965;">
<!ENTITY subsup "&#10963;">
<!ENTITY succapprox "&#10936;">
<!ENTITY succ "&#8827;">

1
任何人将我的想法重新编写成代码,我都会给予+1。我只是懒得动手。 - mogsie
无论如何,您都可以使用单个sed完成,echo foobarbaz | sed -e's/foo/bar/' -e's/baz/quz/' - Evan Carroll

2

我的最佳建议是在提供字符实体名称支持之前不要升级到HTML5或XHTML5。

任何认为&#12345;&mdash;更有意义的人都需要升级大脑。大多数人无法记住庞大的数字表。

我们这些必须保持与现有科学、实时或销售点硬件(或政府网络)兼容的旧操作系统的人不能只是输入字符或从列表中选择它。它将无法正确保存在文件中。

之所以对我们强制执行这一规定,是因为w3c不再希望为DTD文件提供服务,因此我们必须回到石器时代。

像这样提供的任何内容都不应该被弃用。


2

正确答案(现代方式)

我五年前问过这个问题。现在每个浏览器都支持UTF-8。并且,每个UTF-8的版本都包含所有命名字符实体的字形支持。这个问题的最佳解决方案是不再使用命名实体,而是仅提供UTF-8(严格模式),并使用其中的实际字符。

这是所有XML实体的列表。所有这些实体都有UTF-8字符替代方案--这也是它们通常呈现的方式。

例如,考虑以下内容:

U+1D6D8, MATHEMATICAL BOLD SMALL CHI            , b.chi

我想在某个xml变体中,您可以使用&b.chi等内容,在搜索“MATHEMATICAL BOLD SMALL CHI”时,您会发现fileformat.info上的某些页面列出了该字符。此外,在Windows中,您可以键入Alt+1D6D8(1d68d来自XML实体表),或者在Linux中键入Ctrl+Shift+u1D6D8。这将以正确的方式将字符放入您的文档中。

0

使用以下答案:https://dev59.com/RXA75IYBdhLWcg3wlqIT#9003931,我创建了该文件并将其发布为GitHub上的Gist:https://gist.github.com/cerkit/c2814d677854308cef57,供那些需要在文件中使用实体的人使用。

我成功地将其与ASP.NET MVC一起使用,通过将文本文件加载到应用程序对象中,并使用该值和我的(格式良好的)HTML解析System.Xml.XmlDocument。

XmlDocument doc = new XmlDocument();

// load the HTML entities into the document and add a root element so it will load
// The HTML entities are required or it won't load the document if it uses any entities (ex: &ndash;)
doc.LoadXml(string.Format("{0}<root>{1}</root>", Globals.HTML_ENTITIES, control.HtmlText));
var childNodes = doc.SelectSingleNode("//root").ChildNodes;
// do your work here    
foreach(XmlNode node in childNodes)
{
    // or here
}

Globals.HTML_ENTITIES 是一个静态属性,它从文本文件中加载实体并将它们存储在应用程序对象中,或者如果它们已经加载在应用程序对象中,则使用这些值。

public static class Globals
{   
    public static readonly string APPLICATION_KEY_HTML_ENTITIES = "HTML_ENTITIES";

    public static string HTML_ENTITIES
    {
        get
        {
            string retVal = null;
            // load the HTML entities from a text file if they're not in the Application object
            if(HttpContext.Current.Application[APPLICATION_KEY_HTML_ENTITIES] != null)
            {
                retVal = HttpContext.Current.Application[APPLICATION_KEY_HTML_ENTITIES].ToString();
            }
            else
            {
                using (StreamReader sr = File.OpenText(HttpContext.Current.Server.MapPath("~/Content/HtmlEntities/RootHtmlEntities.txt")))
                {
                    retVal = sr.ReadToEnd();
                    HttpContext.Current.Application[APPLICATION_KEY_HTML_ENTITIES] = retVal;
                }
            }

            return retVal;
        }
    }
}

我尝试创建一个长字符串来保存这些值,但它一直导致 Visual Studio 崩溃,所以我决定最好的方法是在运行时加载文本文件并将其存储在应用程序对象中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接