【问题标题】:How to Parsing "Event XML" in Java?如何在 Java 中解析“事件 XML”?
【发布时间】:2008-10-13 16:49:54
【问题描述】:

我希望使用 Java 来解析由远程设备生成的持续事件驱动 XML 流。以下是两个事件的简化示例:

<?xml version="1.0"?>
<Event> DeviceEventMsg
<Param1>SomeParmValue</Param1>
</Event>
<?xml version="1.0"?>
<Event> DeviceEventMsg
<Param1>SomeParmValue</Param1>
</Event>

似乎 SAX 比 DOM 更适合于此,因为它是一个持续的流,尽管我对 Sax 不太熟悉。不要因为 XML 的结构而对我大喊大叫——我已经知道并且无法更改它。

是的,设备确实在每个事件之前发送 xml 指令。我的第一个问题是第二个 xml 处理指令正在破坏 SAX 解析器。

任何人都可以提出一种解决方法吗?


到目前为止,我正在使用的第二条 xml 处理指令的代码是:

public class TestMe extends HandlerBase {
    public void startDocument () throws SAXException
    {
        System.out.println("got startDocument");
    }

    public void endDocument () throws SAXException
    {
        System.out.println("got endDocument");
    }

    public void startElement (String name, AttributeList attrs) throws SAXException
    {
        System.out.println("got startElement");
    }

    public void endElement (String name) throws SAXException
    {
        System.out.println("got endElement");
    }

    public void characters (char buf [], int offset, int len) throws SAXException
    {
        System.out.println("found characters");
    }

    public void processingInstruction (String target, String data) throws SAXException
    {
        System.out.println("got processingInstruction");
    } 

    public static void main(String[] args) {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            SAXParser saxParser = factory.newSAXParser();
            // using a file as test input for now
            saxParser.parse( new File("devmodule.xml"), new TestMe() );

        } catch (Throwable err) {
            err.printStackTrace ();
        }
    }
}

【问题讨论】:

  • 数据流更新速度有多快? xml headers之间的连接是否丢失?
  • 这些事件是家庭自动化设备的开启和关闭事件,因此它们可以相隔几秒钟,但会长时间处于不活动状态。事件之间保持连接。

标签: java xml sax


【解决方案1】:

尝试使用StAX 而不是 SAX。 StAX 提供了更大的灵活性,它是流式 XML 的更好解决方案。 StAX 的实现很少,我对codehaus 很满意,但也有一个来自Sun。 它可能会解决你的问题。

【讨论】:

  • 你知道告诉STAX不要在我上面给出的输入中间的这一行上的方法吗?同样,它在设备提供的内容中是固定的,我无法更改它。
【解决方案2】:

还有一个建议,特别是关于多个 xml 声明。是的,这是非法的 xml,所以正确的解析器会使用默认模式来处理它。 但是一些解析器有备用的“多文档”模式。例如,Woodstox 就有这个,所以您可以查看:

http://www.cowtowncoder.com/blog/archives/2008/04/entry_66.html

基本上,您必须告诉解析器(通过输入工厂)输入是“多个 xml 文档”(ParsingMode.PARSING_MODE_DOCUMENTS)的形式。

如果是这样,它将接受多个 xml 声明,每个声明都表示一个新文档的开始。

【讨论】:

    【解决方案3】:

    如果你打印出开始和结束元素 System.out.println() 的名称,你会得到这样的结果:

    得到了 startDocument 得到了 startElement 事件发现 发现字符 字符得到了 startElement Param1 找到的字符得到 endElement Param1 发现字符得到 endElement 事件 org.xml.sax.SAXParseException: 处理指令目标匹配 不允许使用“[xX][mM][lL]”。 ...

    所以我认为是第二个

    &lt;?xml version="1.0"?&gt;

    没有得到 endDocument 会导致解析器问题。

    【讨论】:

      【解决方案4】:

      如果你添加这个:

      catch(SAXException SaxErr){
              System.out.println("ignore this error");
          }
      

      在其他捕获之前,您将捕获这个特定错误。然后,您必须重新打开设备或对于静态文件情况,您可能需要跟踪您是否在文件中。

      或者在结束事件事件时,关闭设备/文件,然后为下一个事件重新打开它。

      【讨论】:

        【解决方案5】:

        RE:Simon 建议捕获 SAXException 以确定您何时到达一个 XML 文档的结尾并到达另一个 XML 文档的开头,我认为这将是一个有问题的方法。如果发生另一个错误(无论出于何种原因),您将无法判断异常是由于错误的 XML 还是由于您已到达文档末尾而引发的。

        问题在于解析器是用来处理 XML 文档的;不是几个 XML 文档的流。我建议编写一些代码来手动解析传入的数据流,将其分解为包含单个 XML 文档的单个流;然后将这些流串行传递给 XML 解析器(这样可以保证事件的顺序)。

        【讨论】:

        • @sgreeve,同意,根据我的建议,您必须了解如何检查此特定错误,或将任何错误作为文档结尾处理。您的建议很好,在传递给 xml 解析器之前将(通过查找已知模式)预解析为格式良好的文档。
        • 是否没有 XML 解析器可以捕获通过一个连续输入流传入的一系列 XML 文档?
        • XML 解析器旨在解析格式良好的 XML 文档(嗯,从技术上讲,有些可能可以处理文档片段)。您所拥有的不是格式良好的 XML 文档。
        猜你喜欢
        • 1970-01-01
        • 2017-07-27
        • 2013-10-04
        • 2011-05-14
        • 1970-01-01
        • 1970-01-01
        • 2014-12-06
        • 2011-08-11
        • 1970-01-01
        相关资源
        最近更新 更多