0

我在 Android 上使用XmlReaderand编写了一个 Java SAX 解析器DefaultHandler

它不断增长的规模变得笨拙,所以我想做的是将某些元素下的内容的责任委托给“子”处理程序。

假设我有 XML:

<fruit>
   <apples>
      <pips/>
   </apples>
   <oranges>
      <seeds/>
   </oranges>
</fruit>

我打算让原始处理程序实现移交,以分离苹果、橙子等的相应处理程序,并在完成后将这些处理程序收回。

因此,我做了一些这样的事情:

@Override
public void startElement( ... ) ...
{
   //...

   if ( localName.equals("oranges"))
   {
       ContentHandler orangeHandler = new OrangeHandler( xmlReader, this );
       xmlReader.setContentHandler( orangeHandler );
   }

   super.startElement( uri, localName, qName, attributes );
}

然后以类似的方式恢复主处理程序。

我期望看到的:对 startElement()、characters()、endElement() 等的进一步调用转到新的处理程序。

我实际看到的:那个,但是在主处理程序上继续调用这些方法。

Javadoc 说:

公共无效 setContentHandler(内容处理程序处理程序)

允许应用程序注册内容事件处理程序。

如果应用程序没有注册内容处理程序,则 SAX 解析器报告的所有内容事件都将被静默忽略。

应用程序可以在解析过程中注册一个新的或不同的处理程序,并且 SAX 解析器必须立即开始使用新的处理程序。

我可以通过保留我自己是否授权的记录并忽略那些多余的电话来绕过报告行为,但这让我怀疑我是否在做一些愚蠢的事情,以后会咬我。

有没有人有这方面的经验?

4

2 回答 2

2

我认为维护发出回调的原始 SAX 解析器可能更容易,并替换为下面的单独处理程序,这些处理程序只是代理具有不同实现的 SAX 回调方法,但不执行实际的 XML 读取,就像您目前正在做的那样。

例如(在伪代码中)

class SaxHandler {
   SaxProxy proxy = new SaxProxyImpl();
   public void startElement(e) {
      proxy.startElement(e);
   }
}

并根据需要将您换成proxy不同的实现。我怀疑你需要一堆代理,并在适当的endElement()回调时弹出你的堆栈。

于 2013-07-03T11:48:18.437 回答
0

作为一个解决方案,我发现这是我自己的代码中的一个错误 - 与问题中的代码相比,更复杂的现实是我有多个级别的委派,加上对委派点的重新处理,即

   if ( localName.equals("oranges"))
   {
       ContentHandler orangeHandler = new OrangeHandler( xmlReader, this );
       xmlReader.setContentHandler( orangeHandler );
       orangeHandler.startElement( ..., localName, ...);
   }

在这样做的过程中,我对内容处理程序和 startElement 调用的顺序不正确,这 - 在第二次委派时 - 合谋设置了错误的处理程序。

我不认为它会降低我所有的复杂性,但@Brian 的设计选择会简化解析流程本身的委托,所以我接受它作为答案。

于 2013-07-03T12:19:39.833 回答