用Java解析包含XML片段的文件

问题描述:

我继承了一个“XML”许可证文件,其中包含两个XML片段(<XmlCreated><Product>),所以当我试图解析文件时,我(期望地)得到一个错误一份文件不完整。用Java解析包含XML片段的文件

我需要同时获得XmlCreatedProduct标签。

示例XML文件:

<?xml version="1.0"?> 

<XmlCreated>May 11 2009</XmlCreated> 

<!-- License Key file Attributes --> 
<Product image ="LicenseKeyFile"> 

<!-- MyCompany --> 
<Manufacturer ID="7f"> 
    <SerialNumber>21072832521007</SerialNumber> 
    <ChassisId>72060034465DE1C3</ChassisId> 
    <RtspMaxUsers>500</RtspMaxUsers> 
    <MaxChannels>8</MaxChannels> 
</Manufacturer> 

</Product> 

这里是我用它来尝试加载XML当前的代码。它不起作用,但我之前将它用作格式良好的XML的起点。

public static void main(String[] args) { 
    try { 
     File file = new File("C:\\path\\LicenseFile.xml"); 
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder db = dbf.newDocumentBuilder(); 
     Document doc = db.parse(file); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

db.parse(file)线,我得到以下异常:

[Fatal Error] LicenseFile.xml:6:2: The markup in the document following the root element must be well-formed. 
org.xml.sax.SAXParseException: The markup in the document following the root element must be well-formed. 
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source) 
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source) 
at javax.xml.parsers.DocumentBuilder.parse(Unknown Source) 
at com.mycompany.licensesigning.LicenseSigner.main(LicenseSigner.java:20) 

我怎么会去分析这个令人沮丧的文件吗?

如果你知道这个文件总是会非正常形成的...做到这一点。在最后一个数据之后,在<?xml...></root>之后添加一个新的虚拟<root>标记。

如何在InputStream中实现一个简单的包装器,该包装器使用根级标签打包文件的输入,并将其用作DocumentBuilder.parse()的输入?

如果预期输入小到足以加载到内存中,读入一个字符串,用一个虚拟的开始/结束标签包装它,然后使用:

DocumentBuilder.parse(new InputSource(new StringReader(string))) 

你将需要创建两个通过将文件拆分成更小的片段并单独解析这些片段(或者通过添加包含它们的标签将它们重建为更大的文档)来分离Document对象。

如果你可以依靠文件的结构应该很容易将文件读入一个字符串,然后搜索子像<Product</Product>,然后使用这些标记来创建你可以传递到一个文档构建一个字符串。

我可能会创建一个SequenceInputStream,其中你用两个ByteArrayInputStreams夹着真正的流,返回一些虚拟根开始标记和结束标记。

然后,我会使用使用流而不是文件名的解析方法。

我同意Jim Garrison在某种程度上使用InputStream或StreamReader并将输入包装在所需的标签中,这是一种简单易行的方法。我可以预见的主要问题是,您必须检查有效和无效的格式(如果您希望能够对有效和无效数据使用该方法),如果格式无效(由于缺少根级标记)用标签包装输入,如果其有效,则不包装输入。如果由于某些其他原因导致输入无效,则还可以更改输入来纠正格式问题。

此外,它可能更好地存储在字符串集合(某种)而不是字符串本身,这将意味着你不会有尽可能多的输入大小的限制。使每个字符串从文件中移出一行。你最终应该建立一个合理且易于遵循的结构,这样可以更容易地纠正未来其他格式问题。

最难的部分是搞清楚导致无效格式化的原因。在你的情况下,检查根级标签,如果标签存在并格式正确,不要换行,否则换行。