根据PHP中的W3C规范化Unicode

根据PHP中的W3C规范化Unicode,php,unicode,normalization,web-standards,unicode-normalization,Php,Unicode,Normalization,Web Standards,Unicode Normalization,在中验证网站的HTML代码时,我收到以下警告: Line 157, Column 220: Text run is not in Unicode Normalization Form C. …i͈̭̋ͥ̂̿̄̋̆ͣv̜̺̋̽͛̉͐̀͌̚e͖̼̱ͣ̓ͫ͆̍̄̍͘-̩̬̰̮̯͇̯͆̌ͨ́͌ṁ̸͖̹͎̱̙̱͟͡i̷̡͌͂͏̘̭̥̯̟n̏͐͌̑̄̃͘͞… 我正在PHP5.3.x中开发它,所以我可以使用这个类 因此,为了解决这个问题,我应该在显示用户的任何输入(例如注释)时使用Normalizer:

在中验证网站的HTML代码时,我收到以下警告:

Line 157, Column 220: Text run is not in Unicode Normalization Form C.

…i͈̭̋ͥ̂̿̄̋̆ͣv̜̺̋̽͛̉͐̀͌̚e͖̼̱ͣ̓ͫ͆̍̄̍͘-̩̬̰̮̯͇̯͆̌ͨ́͌ṁ̸͖̹͎̱̙̱͟͡i̷̡͌͂͏̘̭̥̯̟n̏͐͌̑̄̃͘͞…
我正在PHP5.3.x中开发它,所以我可以使用这个类

因此,为了解决这个问题,我应该在显示用户的任何输入(例如注释)时使用
Normalizer::normalize($output)
,还是应该在将任何用户输入存储到数据库之前使用
Normalizer::normalize($input)


tl;dr:我应该在将用户输入存储到数据库中之前使用,还是在显示时使用?

根据应用程序的用途和性质,由您决定是在读取用户输入时应用规范化,还是将其存储到数据库中,还是在写入时应用规范化,或者根本不应用规范化。总结问题评论中提到的长线索,也可在

  • 警告信息来自实验性的“HTML5验证”(这实际上是一个过梁,除了一些正式测试之外,还应用了主观规则)
  • 这条信息不是基于HTML5草案中的任何要求,而是基于对可能导致某些软件出现问题的观点
  • 这些意见最初让“HTML5验证”发出一条错误消息,现在是一条警告
当然,作为用户输入获取非规范化数据是可能的,尽管不常见。这并不取决于浏览器执行的规范化(他们不做这样的事情,尽管将来可能会这样做),而是取决于输入方法和习惯。例如,键入字母u(u umlaut,或u带分隔符)的方法倾向于以预合成形式生成字符,如标准化的。人们可以用非规范化的、分解的形式生成它,如字母u后跟组合的分音符,但他们通常没有理由这样做,而且大多数人甚至不知道如何做到这一点

如果在软件中进行字符串比较,它们可能会(取决于使用的比较例程)将预合成的ü视为与分解的表示相等。简单实现将它们视为不同的,因为它们在简单字符级别(Unicode代码点)上绝对不同

最晚在编写阶段的某个时候进行规范化的一个原因是预合成字符通常会显示得更可靠。要呈现标准化的字体,程序只需从字体中拾取字形。要呈现分解的ü,程序必须将其识别为规范等效于规范化的ü,或者在书写字母u时,在字母u上方正确放置一个分划符号,并适当注意u字形的图形属性,而许多程序在这方面都失败了


另一方面,在接收非规范化数据作为用户输入的罕见情况下,用户很可能有理由生成它。他可能认为规范化u和非规范化u是不同的,需要这样对待。

严格地说,web字符模型的规则不仅仅是一个人应该规范化为NFC,而是任何包含来自另一个机制的文本的技术运行之前和之后的表单都应该在NFC中。例如XML包含、字符引用和实体引用。例如,
不适合角色模型,因为它在NFC中,扩展角色引用会将其变成
a
,然后是组合的diareses,这不是NFC。大多数情况下,避免这种情况在实践中非常容易,但值得注意


U+0338有一个有趣的例子<代码>>
后跟U+0338将标准化为
在页面上显示的是什么类型的数据?这似乎更像是验证器的问题,而不是您的数据的问题。用户可以合法地发布类似的内容。这只是一堆带有大量上标和下标的文本,看起来很糟糕。有趣:)我确信验证器会因为这种字符的某种组合而崩溃。。。但我也发现这条线索对林克曼来说很有用,我不知道这是一个如此复杂的主题。我想我会把一切正常化以防万一。。只要验证器高兴,导航器就应该是tooYeah,这个线程是无止境的…:-)回答得很好,非常详细,经过深思熟虑。然而,我不同意最后一段。。。如果两种输入字母u的方法(无论是u-umlaut还是u-with-diaeresis)的结果都是u-完全相同的字符,没有人类可见的差异-,为什么要将它们视为不同的东西?我在这里可能错了,但这不是一个应该使用规范化的完美例子吗?作为文本,它们应该被认为是等价的。如果有操作也将它们视为八位字节,那么它们就不能。一个例子是,如果他们有一个数字签名-正常化将改变它,使它不再是什么签署。这就是XML签名作为实际签名的一部分有一个规范化步骤的原因,因此只有NFC才会被签名。当输出为HTML时,它将输出为文本,这是不相关的,因此它仍然应该是NFC,但您可能有理由保留发送的表单。@John Doe,它们不会产生相同的字符,而是产生一个字符和一个两个字符的序列,这在规范上是等效的。规范等价不是一个恒等式,程序可以处理can。虽然我们不应该期望程序这样做,但等效字符是不同的。由于我提到的渲染机制(例如,通过直接使用字形显示预合成的ü,但通过使用“u”字形显示分解的ü,并在其上放置“()”,有时甚至从另一种字体中取变音!),因此规范对等甚至不意味着视觉识别。