Nig*_*awk 30 php xml entity tinymce simplexml
我已经在这个问题上搜索了stackoverflow,并找到了一些主题,但我觉得在这方面我没有真正的答案.
我有一个用户提交的表单,字段的值存储在XML文件中.XML设置为使用UTF-8编码.
用户将不时地从某处复制/粘贴文本,当我得到"实体未定义错误"时.
我意识到XML只支持少数几个实体,除此之外的任何东西都无法识别 - 因此解析器错误.
从我收集的内容中,我看到了一些选项:
 并将它们与 实际空间交换出来.我正在对XML文件做的是,用户可以将内容输入到表单中,将其存储在XML文件中,然后该内容在Web页面上显示为XHTML(使用SimpleXML解析).
在我不了解的三个选项或任何其他选项中,处理这些实体的最佳方法是什么?
谢谢,瑞恩
UPDATE
我要感谢大家的好评.我确实确定了导致我的实体错误的原因.所有的建议让我更深入地研究它!
一些文本框中有普通的旧文本框,但我的textareas使用TinyMCE进行了增强.事实证明,在仔细观察的同时,PHP警告总是引用来自TinyMCE增强型textareas的数据.后来我注意到在PC上所有角色都被取出了(因为它无法读取它们),但是在MAC上你可以看到引用该角色的unicode号的小方框.它首先出现在MAC上的正方形中的原因是因为我使用utf8_encode来编码不是UTF的数据以防止其他解析错误(这在某种程度上也与TinyMCE有关).
所有这些的解决方案非常简单:
我entity_encoding : "utf-8"在tinyMCE.init中添加了这一行.现在,所有角色都以他们应该的方式出现.
我想我唯一不理解的是为什么当放置在文本框中时字符仍然显示,因为没有任何东西将它们转换为UTF,但是使用TinyMCE这是一个问题.
小智 22
我同意这纯粹是一个编码问题.在PHP中,这就是我解决这个问题的方法:
在将html片段传递给SimpleXMLElement构造函数之前,我使用了解码它html_entity_decode.
然后使用进一步编码utf8_encode().
$headerDoc = '<temp>' . utf8_encode(html_entity_decode($headerFragment)) . '</temp>'; 
$xmlHeader = new SimpleXMLElement($headerDoc);
现在上面的代码不会抛出任何未定义的实体错误.
Tom*_*lak 15
您可以对文本进行HTML解析,并仅使用相应的数字实体重新转义(例如: →  ).无论如何 - 简单地使用未经过消毒的用户输入是一个坏主意.
所有数字实体被允许在XML,只能从HTML中已知的名为那些不工作(有例外&,",<,>,').
但大多数情况下,您只需将实际字符(ö→ ö)写入XML文件即可,因此根本不需要使用实体引用.如果你使用DOM API来操纵你的XML(你应该!),这是你最安全的选择.
最后(这是一个懒惰的开发人员解决方案)你可以构建一个破碎的XML文件(即没有格式良好,有实体错误),只需通过整理就可以进行必要的修复.这可能会起作用或者可能会失败,这取决于整个事情是多么破碎.根据我的经验,整洁非常聪明,让你逍遥法外.
1。我可以找到并替换所有 [ ?] 并将它们替换为 [ ?] 或实际空格。
这是一个强大的方法,但它要求您有一个包含所有 HTML 实体的表(我假设粘贴的输入来自 HTML)并解析粘贴的文本以获取实体引用。
2。我可以将有问题的代码放在 CDATA 部分中。
换句话说,禁用整个部分的解析?那么你就必须以其他方式解析它。可以工作。
3。我可以将这些实体包含在 XML 文件中。
您的意思是包括实体定义?我认为,如果您不介意使 XML 文件变得更大一些,那么这是一种简单而可靠的方法。您可能有一个“包含”文件(在网上找到一个),它是一个外部实体,您可以从主 XML 文件的顶部引用它。
一个缺点是您使用的 XML 解析器必须是处理外部实体的解析器(并非所有解析器都需要这样做)。并且它必须正确地将外部实体的(可能是相对的)URL 解析为可访问的内容。这还不错,但可能会增加对处理工具的限制。
4。您可以禁止粘贴内容中的非 XML。除此之外,这将不允许未在 XML 中预定义的实体引用(Tomalak 提到的 5 个)或在内容本身中定义的实体引用。然而,如果用户需要能够将 HTML 粘贴到其中,这可能会违反应用程序的要求。
5。您可以通过设置 someDiv.innerHTML = thePastedContent; 将粘贴的内容解析为 HTML 到 DOM 树中。换句话说,在某处创建一个div(可能是display=none,除了调试)。假设您有一个 javascript 变量myDiv保存此 div 元素,另一个变量myField保存输入文本字段的元素。然后在 javascript 中你做
myDiv.innerHTML = myField.value;
它从 myField 中获取未解析的文本,将其解析为 HTML DOM 树,并将其作为 HTML 内容粘贴到 myDiv 中。
然后,您将使用一些基于浏览器的方法将 DOM 树序列化(=“解析”)回 XML。例如,参见这个问题。然后将结果以 XML 形式发送到服务器。
您是否想在浏览器或服务器上进行此修复(如@Hannes建议的那样)将取决于数据的大小、响应的速度、您的服务器的强大程度以及您是否关心黑客发送故意使用格式不正确的 XML。