预处理未成形的XML(Java)

时间:2016-09-05 21:30:35

标签: java xml xml-parsing

我正在使用的XML文件未成型,因此无效。它提出了以下问题:

  • 多个XML声明(错误消息:不允许处理指令匹配“[xX] [mM] [lL]”。
  • 缺少根元素(错误消息:文档末尾的额外内容

    该文件包含多条记录,这是一个包含两条记录的摘录:

<?xml version="1.0" encoding="utf-8"?>
<ElementAa xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="some-namespace">
  <ElementBa attributeB1="11111" attributeB2="someDate">
    <ElementCa attributeC1="someString" attributeC2="someOtherDate">
      <ElementDa attributeD1="12345" />
    </ElementCa>
    <ElementEa attributeE1="ABCD" />
  </ElementBa>
</ElementAa>
<?xml version="1.0" encoding="utf-8"?>
<ElementAb xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="some-namespace">
  <ElementBb attributeB1="22222" attributeB2="AgainDate">
    <ElementCb attributeC1="anotherString" attributeC2="yetAnotherDate">
      <ElementDb attributeD1="67891" />
    </ElementCb>
    <ElementEb attributeE1="EFGHI" />
  </ElementBb>
</ElementAb>

为了形成良好和有效,上述文件应该变成这个(如果我错了请纠正我):

<?xml version="1.0" encoding="utf-8"?>
<ElementAa xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="some-namespace">
<ElementBa attributeB1="11111" attributeB2="someDate">
    <ElementCa attributeC1="someString" attributeC2="someOtherDate">
        <ElementDa attributeD1="12345"/>
    </ElementCa>
    <ElementEa attributeE1="ABCD"/>
</ElementBa>
<ElementBb attributeB1="22222" attributeB2="AgainDate">
    <ElementCb attributeC1="anotherString" attributeC2="yetAnotherDate">
        <ElementDb attributeD1="67891"/>
    </ElementCb>
    <ElementEb attributeE1="EFGHI"/>
</ElementBb>
</ElementAa>

虽然我知道在所有可能的世界中,数据应该是高质量的,不幸的是我将不得不处理一个糟糕的数据集,我正在努力找到一个良好的方法来实现一个良好的形式和有效XML。目前,我编写了2个实用程序方法,删除所有XML声明(使用模式/匹配器进行正则表达式)并注入文件顶部所需的唯一一个,我将要执行类似的操作以删除任何额外的根节点元素并且只保留<ElementAa xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="some-namespace">

我不认为这种方法特别理想,我担心在处理大文件时会出现很大问题,你能帮忙吗?任何建议,建议,潜在的方法将不胜感激!我真的在为所描述的场景寻找一个好的方法。

非常感谢你,

予。

编辑1: 如上所述,XML内容位于.txt文件中,我编写的2个实用程序方法使用公共BufferedReader来读取其内容。我试图在重命名扩展名为.xml的文件之前进行所有“数据清理”(我还有另一个实用程序)并将其提供给JaxB解析器。

编辑2:不幸的是,当我直接从FTP读取文件时,我无法控制XML生成。最好控制多个XML如何连接到我提供摘录的结果中,但这是不可能的。

1 个答案:

答案 0 :(得分:1)

基本上,您的任务是为语法编写解析器,该语法与XML的语法有一些相似之处。在为任何语法编写解析器之前,您需要定义该语法是什么:即,指定您的工具将接受哪些输入,可能是根据XML语法的变化。

当然,这将是昂贵的:标准化的目的是降低成本,以便每个人都可以使用相同的语法和相同的解析器,如果人们使用专有的变体,那么生活对每个人来说都会变得更复杂。

到目前为止,您要求我们通过向我们展示一个示例来猜测您的异常XML的语法。好吧,一个例子没有做出规范。更严重的是,为一种未经指定的语言编写解析器,通过不断扩展它来处理越来越多的例子是行不通的:Sisyphus将在你完成任务之前完成任务。

你还应该记住,你拿起别人的垃圾越好,他们扔给你的垃圾就越多。

<强>附录

实际上,如果输入文件包含一系列格式良好的XML文档连接成一个文件,那么输入的语法实际上可以很容易地指定。这只是XML规范中添加的一条额外规则:

file ::= document+

可能修改了文档开头的XML声明是强制性的。

因此,定义您想要接受的语法可能并不太难。但编写一个准确接受这种语法的解析器仍然是一个挑战。最干净的方法可能是采用开源XML解析器并对其进行修改。

没有办法用正则表达式解析这个语法:它不是常规语言(如果你不明白这意味着什么,你不应该编写解析器,但实质上它意味着语法的定义是递归)。

但是你可以使用一些技巧。每个文档都以<?xml开头,<?xml唯一可以出现的地方是:(a)文档开头,(b)注释,(c)CDATA部分。注释和CDATA部分不能嵌套,所以我认为你的语言的每个实例都符合更简单的语法:

(`<?xml` (stuff | cdata | comment)* )*

其中stuff被定义为不包含<?xml<![CDATA[<!--)的任何内容,cdata和comment定义为XML格式。

根据这种更简单(非递归)语法解析文档足以识别文档边界,并且完成后您可以将每个文档传递给常规XML解析器。