如何在Java中解析“事件XML”?

时间:2008-10-13 16:49:55

标签: java xml sax

我希望使用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 ();
        }
    }
}

5 个答案:

答案 0 :(得分:1)

尝试使用StAX代替SAX。 StAX允许更大的灵活性,它是流式XML的更好解决方案。很少有StAX的实现,我对codehaus的实现感到非常满意,但也有一个来自Sun。 它可能会解决你的问题。

答案 1 :(得分:1)

还有一个建议,特别是有关多个xml声明的建议。是的,这是ILLEGAL xml,因此正确的解析器将使用默认模式对其进行barf。 但是一些解析器具有备用的“多文档”模式。例如,Woodstox有这个,所以你可以查看:

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

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

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

答案 2 :(得分:0)

如果您打印出开始和结束元素System.out.println()的名称,您将得到如下内容:

  

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

所以我认为第二个

  

<?xml version="1.0"?>

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

答案 3 :(得分:0)

如果你添加:

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

在其他捕获之前,您将捕获此特定错误。然后你必须重新打开设备或静态文件的情况下你可能需要跟踪你在文件中。

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

答案 4 :(得分:0)

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

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