1

タグに関係なく、xmlファイルを解析し、そのすべての葉のテキストを読み取る必要があります(テキスト要素のみ)。StAXを使用していますが、要素がテキストのみであることを事前に知る方法がないようです(したがって、getElementTextは要素を残さないための例外をスローします)。そこで、フィルターを使用して、タグ要素のみをフィルター処理し、次のようにドキュメントを繰り返しスローすることにしました。

InputStream in = null;
    try {
        in = new FileInputStream("file.xml");
        DatiEstratti de = DatiEstratti.getInstance();

        // Processamento ad eventi
        XMLInputFactory factory = (XMLInputFactory) XMLInputFactory.newInstance();

        XMLEventReader eventReader = factory.createXMLEventReader(in);
        // usa il filtro per filtrare solo i tag element
        eventReader = factory.createFilteredReader(eventReader, new ElementOnlyFilter());

        while (eventReader.hasNext()) {

            XMLEvent event = eventReader.nextEvent();

            if (event.getEventType() == XMLStreamConstants.START_ELEMENT) {
                StartElement startElement = event.asStartElement();

                XMLEvent peekEvent = eventReader.peek();
                if(peekEvent.isEndElement()){
                    // questa è la prima volta che viene fatto un pop
                    // quindi è una foglia.
                    // recupera il dato.
                    String value = eventReader.getElementText();

                    logger.info("dato : " + value);
                }


                String nome = startElement.getName().getLocalPart();
                String prefix = startElement.getName().getPrefix();
                if (prefix != null) {
                    nome = prefix + ":" + nome;
                }
                de.push(nome);
                logger.info("push : " + de.stampaPercorso());



            } else if ((event.getEventType() == XMLStreamConstants.END_ELEMENT)) {

                de.pop();
                logger.info("pop : " + de.stampaPercorso());
                if (0 > de.nLivelliPercorso()) {
                    break;
                }
            }
            //handle more event types here...
        }

...ここで、フィルターは次のとおりです。

public class ElementOnlyFilter implements EventFilter, StreamFilter {

/* implementation of EventFilter interface */
@Override
public boolean accept(XMLEvent event) {
    return acceptInternal(event.getEventType(  ));
}

/* implementation of StreamFilter interface */
@Override
public boolean accept(XMLStreamReader reader) {
    return acceptInternal(reader.getEventType(  ));
}

/* internal utility method */
private boolean acceptInternal(int eventType) {
    return eventType == XMLStreamConstants.START_ELEMENT
            || eventType == XMLStreamConstants.END_ELEMENT;
}

}

問題は、休暇が見つかったときに次の例外が発生したことです。

    javax.xml.stream.XMLStreamException: ParseError at [row,col]:[3,42]
Message: parser must be on START_ELEMENT to read next text
    at com.sun.xml.internal.stream.XMLEventReaderImpl.getElementText(XMLEventReaderImpl.java:114)
    at javax.xml.stream.util.EventReaderDelegate.getElementText(EventReaderDelegate.java:88)
    at xmlparser.XmlParser.main(XmlParser.java:63)

どうしよう。このコードに誤りはありますか?peek()はリーダーを変更しないので、getElementText()はstart要素によって呼び出される必要があると思いました。私の目標を達成する別の方法はありますか?

4

1 に答える 1

5

まず、開始要素イベントと終了要素イベントのみを含めるようにフィルタリングすると、リーフノード内に含まれるテキストはまったく表示されません。次のように、フィルタリングされていないストリームを使用して、別のアプローチを使用します。

XMLEventReader eventReader = factory.createXMLEventReader(in);
StringBuilder content = null;
while(eventReader.hasNext()) {
  XMLEvent event = eventReader.nextEvent();
  if(event.isStartElement()) {
    // other start element processing here
    content = new StringBuilder();
  } else if(event.isEndElement()) {
    if(content != null) {
      // this was a leaf element
      String leafText = content.toString();
      // do something with the leaf node
    } else {
      // not a leaf
    }
    // in all cases, discard content
    content = null;
  } else if(event.isCharacters()) {
    if(content != null) {
      content.append(event.asCharacters().getData());
    }
  }
  // other event types here
}

秘訣はcontent = null、終了要素セクションの最後にあります。if(event.isEndElement())ブロックに入るときに、contentがnullでない場合、このイベントとそれに対応する開始タグの間に終了要素イベントが介在していないことがわかります。つまり、リーフノードです。

于 2012-07-02T10:07:27.633 に答える