在Java中解析包含XML片段的文件

时间:2010-07-12 20:40:06

标签: java xml parsing

我继承了一个“XML”许可证文件,其中不包含根元素,而是两个XML片段(<XmlCreated><Product>),所以当我尝试解析文件时,我(期待)会出错关于文件不完整的文件。

我需要同时获取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)

我如何解析这个令人沮丧的文件?

5 个答案:

答案 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存储在一些字符串(某种类型)而不是字符串本身中可能更好,这意味着您不会对输入大小有任何限制。从文件中将每个字符串设为一行。您最终应该采用符合逻辑且易于遵循的结构,以便在将来更容易纠正其他格式问题。

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