我继承了一个“XML”许可证文件,其中不包含根元素,而是两个XML片段(<XmlCreated>
和<Product>
),所以当我尝试解析文件时,我(期待)会出错关于文件不完整的文件。
我需要同时获取XmlCreated
和Product
代码。
示例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)
我如何解析这个令人沮丧的文件?
答案 0 :(得分:2)
如果你知道这个文件总是不完整的......那就这样吧。在最后一个数据之后的<root>
和<?xml...>
之后添加新的虚拟</root>
标记。
答案 1 :(得分:1)
您需要创建两个单独的Document对象,方法是将文件分成更小的部分并单独解析这些部分(或者通过添加包含它们的标记将它们重建为更大的文档)。
如果您可以依赖文件的结构,则应该很容易将文件读入字符串,然后搜索<Product
和</Product>
之类的子字符串,然后使用这些标记创建字符串你可以传入文档构建器。
答案 2 :(得分:0)
如何在InputStream周围实现一个简单的包装器,它使用根级别标签包装文件的输入,并将其用作DocumentBuilder.parse()
的输入?
如果预期输入足够小以加载到内存中,请读入字符串,用虚拟开始/结束标记包装然后使用:
DocumentBuilder.parse(new InputSource(new StringReader(string)))
答案 3 :(得分:0)
我可能会创建一个SequenceInputStream,用两个ByteArrayInputStreams将实际流夹在中间,返回一些虚拟根开始标记和结束标记。
然后我会使用带有流而不是文件名的parse方法。
答案 4 :(得分:0)
我同意Jim Garrison在某种程度上使用InputStream或StreamReader并将输入包装在所需的标签中,这是一种简单易行的方法。我可以预见的主要问题是,如果格式无效(因为缺少根级别标签),您必须对有效和无效格式进行一些检查(如果您希望能够将该方法用于有效和无效数据) )使用标记包装输入,如果有效则不包装输入。如果由于某些其他原因输入无效,您还可以更改输入以更正格式问题。
此外,将ipnut存储在一些字符串(某种类型)而不是字符串本身中可能更好,这意味着您不会对输入大小有任何限制。从文件中将每个字符串设为一行。您最终应该采用符合逻辑且易于遵循的结构,以便在将来更容易纠正其他格式问题。
最难的部分是弄清楚导致无效格式化的原因。在你的情况下,只检查根级别标签,如果标签存在并且格式正确,不要换行,如果没有,换行。