我从第三方获得了一个我必须在我的应用程序中导入的XML文件,并且XML包含未转义和未转换的元素。在内部文本中,他们不会解决这个问题!所以我的问题是处理这个问题的最佳方法是什么?
这个XML非常大,而且修复速度必须很快,我的第一个解决方案就是替换&有&符号的字符,但实际上我不喜欢这个“解决方案”,原因很明显。我不知道如何使用XmlStringReader与这样的XML,因为在这样的行上抛出异常,所以我不能在内部文本上使用HtmlEncode。我试图将XmlTextReader Settings.CheckCharacters
设置为false但没有结果。
以下是样本,&在元素中,并且在该字段中可以是某些公司名称中的任何内容,因此我的替换修复可能不适用于某些其他公司名称,我想以某种方式使用HtmlEncode,但当然仅在内部文本上。
<komitent ID="001398">
<sifra>001398</sifra>
<redni_broj>001398</redni_broj>
<naziv>LJUBICA & ŽARKO</naziv>
<adresa1>Odvrtnica 27</adresa1>
<adresa2></adresa2>
<drzava>HRVATSKA</drzava>
<grad>Zagreb</grad>
</komitent>
答案 0 :(得分:4)
下面的关键信息是,除非您知道输入文件的确切格式,并保证与XML的任何偏差是一致的,否则您无法以编程方式进行修复,而不会担心您的修补程序不正确。
当且仅在以下情况下,将&
替换为&
进行修复是可接受的解决方案:
这些数据没有可接受的格式良好的来源。
这是一次性(或至少非常罕见)的导入。
您可以继续迭代,为其设计新的修补程序,在遇到问题时为每个问题添加解决方案。
&
字符“修复”它,就会出现其他错误。您有资源手动检查“已修复”数据的完整性。
文档中没有格式正确的实体 -
只需将&
替换为&
,就会错误地将"
更改为&quot;
。你可能能够解决这个问题,但不要天真地对它有多么棘手(实体可能在DTD中定义,可能指的是unicode代码点......)
如果它是一个行为异常的特定元素,您可以考虑使用<![CDATA
]]>
包装元素的内容,但这仍然依赖于您能够找到开始和结束标签可靠。
答案 1 :(得分:2)
首先改变你的心态。输入不是XML,因此不要将其称为XML。甚至不要使用“xml”标记您的问题。事实上它不是XML意味着您不能使用任何XML工具,并且您无法获得XML数据交换的任何好处。您正在处理没有规范且没有任何工具的专有格式。像对待任何其他专有格式一样对待它 - 尝试发现您获得的规范,并为其编写解析器。
答案 2 :(得分:2)
如果你知道文件的标签,并希望“标记”可能有可疑数据的标签内的文字,你可以这样做:
private static string FixBadXmlText(string xmlText)
{
var unreliableTextTags = new[] { "message", "otherdata", "stacktrace", "innerexception" };
foreach(var tag in unreliableTextTags)
{
string openTag = "<" + tag + ">";
string closeTag = "</" + tag + ">";
xmlText = xmlText.Replace(openTag, openTag + "<![CDATA[").Replace(closeTag, "]]>" + closeTag);
}
return xmlText;
}
CDATA Section(<![CDATA[ {your text here} ]]>
)内的任何内容都不会被XML解析器解释,因此不需要进行转义。当我想解析一些没有正确转义输入的糟糕的XML时,这对我有所帮助。
答案 3 :(得分:0)
由于您的起始XML是错误的,因此无法使用任何XmlReaders,因为它们无法正确读取它。
如果只有XML节点的值不是htmlEncoded,那么你必须手动读取行,解析(获取xml节点名称及其值),编码并输出到新文件。
我们经常会遇到类似的情况所以我理解你的痛苦 - 大部分时间,错误都有一些“规则”,所以我猜这里他们没有编码商业名称(也许是街道名称),所以你可以只搜索那个字符串<naziv>
,它正在关闭标签</naziv>
和HtmlEncode之间的所有内容。此外,由于它的商业名称,它不会有换行符,这可以让你的生活相当轻松......
答案 4 :(得分:0)
您可以尝试使用正则表达式,具体取决于结构的复杂程度:
Regex mainSplitter = new Regex("<komitent ID=\"([0-9]*)\">(.*?)</komitent>");
Regex nazivFinder = new Regex("<naziv>(.*?)</naziv>");
foreach (Match item in mainSplitter.Matches(test))
{
Console.WriteLine(item);
string naziv = null;
Match node = nazivFinder.Match(item.Groups[2].Value);
if (node != null)
naziv = node.Groups[1].Value;
}
答案 5 :(得分:0)
您可以将文件作为XPL处理,甚至使用XPL解析器将这些文件转换为有效的XML。 XPL(可扩展进程语言)就像XML一样,但解析器允许XML在文本字段中使用“特殊字符”。因此,您实际上可以通过XPL进程运行无效的XML文件(由于特殊字符而无效)。在某些情况下,您可以使用XPL处理器而不是XML处理器。您还可以使用它来预处理无效文件,而不会造成任何性能损失。 Artificial Intelligence, XML, and Java Concurrency