在Java中解析没有根元素的XML文件

5

我有一个没有根节点的XML文件。除了手动添加一个“虚假”的根元素外,是否有任何方法可以在Java中解析XML文件?谢谢。


3
如果没有根节点,它就不算是一个真正的XML文件。是否由于某种原因而无法添加“虚拟”根节点,或者你只是对其他替代方案感兴趣? - Anon.
1
匿名,谢谢你的回复,我想找一个更优雅的解决方案。我知道这很讽刺,我正在寻找一个优雅的解决方案来解决一个有缺陷的问题。不过,我只是想知道是否还有其他选择。 - Seagull
我真的希望没有这样的选项。为什么呢?因为像那样“放松”的标准遵从性根本不利于对这些标准的执行。而且,希望有更多的人不愿意处理非规范的自制“标准”(比如非格式良好的 XML),而不是愿意处理它们的人。 - shylent
即使您可以正确解析它,您期望的输出是什么?一系列顶级元素的文档节点吗?这仍然非常笨拙。而且它与自己包装并将它们拉出来没有什么区别。 - j flemm
6个回答

5

我觉得你可以创建一个新的InputStream实现,它包装了你要解析的那个流。这个实现会在包装流的字节之前返回开头根标签的字节,在包装流的字节之后返回结束根标签的字节。这个实现相当容易实现。

我也可能面临这个问题。遗留代码,对吧?

Ian。

编辑:你还可以查看java.io.SequenceInputStream,它允许你将流附加到另一个流上。你需要将前缀和后缀放入字节数组中,并将它们包装在ByteArrayInputStreams中,但这都是相当简单的。


+1:这是我在类似情况下所做的,而且确实很容易。 - Don Roby

4

您的XML文档需要一个根xml元素才能被认为是格式正确的。如果没有根元素,您将无法使用XML解析器对其进行解析。


谢谢krock的回复。我很清楚XML格式良好的规则。然而,我正在处理一个糟糕的遗留场景,这就是我必须使用的,所以我在寻找选项。谢谢。 - Seagull

3
一种方法是提供自己的虚拟包装器,而不触碰原始的“xml”(即不规范的“xml”)。需要翻译的词是“dummy wrapper”。 语法
<!DOCTYPE some_root_elem SYSTEM "/home/ego/some.dtd"
[
  <!ENTITY entity-name "Some value to be inserted at the entity">
]

示例:

<!DOCTYPE dummy [
<!ENTITY data SYSTEM "http://wherever-my-data-is">
]>
<dummy>
&data;
</dummy>

这仍然是将某些内容包装在XML周围。我要找的是,在Java中是否有一种通过在某个API中设置某些属性来解析此XML的方法。 - Seagull
1
你可以在程序内部使用字符串作为外部包装器,它实际上不需要存在于文件系统中。 - Donal Fellows

1
你可以使用另一个解析器,比如Jsoup。它可以解析没有根节点的XML。

0

我认为即使有任何API提供此选项,它也只会返回“XML”的第一个节点,看起来像根节点并且舍弃其余部分。

因此,答案可能是自己完成。Scanner或StringTokenizer可能会有所帮助。

也许一些HTML解析器可以帮助,它们通常不太严格。


0

这是我所做的:

有一个旧的java.io.SequenceInputStream类,它非常古老,使用的是Enumeration而不是List或其他。

使用它,您可以在无根XML流周围添加根元素标签(在我的情况下为<div></div>)。 (由于性能和内存原因,不应通过连接字符串来执行此操作。)

public void tryExtractHighestHeader(ParserContext context)
{
    String xhtmlString = context.getBody();
    if (xhtmlString == null || "".equals(xhtmlString))
        return;

    // The XHTML needs to be wrapped, because it has no root element.
    ByteArrayInputStream divStart = new ByteArrayInputStream("<div>".getBytes(StandardCharsets.UTF_8));
    ByteArrayInputStream divEnd = new ByteArrayInputStream("</div>".getBytes(StandardCharsets.UTF_8));
    ByteArrayInputStream is = new ByteArrayInputStream(xhtmlString.getBytes(StandardCharsets.UTF_8));
    Enumeration<InputStream> streams = new IteratorEnumeration(Arrays.asList(new InputStream[]{divStart, is, divEnd}).iterator());

    try (SequenceInputStream wrapped = new SequenceInputStream(streams);) {
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = builderFactory.newDocumentBuilder();
        Document xmlDocument = builder.parse(wrapped);

从这里开始,你可以做任何你想做的事情,但要记住额外的元素。

        XPath xPath = XPathFactory.newInstance().newXPath();
    }
    catch (Exception e) {
        throw new RuntimeException("Failed parsing XML: " + e.getMessage());
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接