2012-03-01 8 views
2

これは私にとってさえ愚かな質問のようですが、答えが見つからないものの1つです。STaxを使用したJavaでのXMLの解析

イムこのようなルックスを解析しようとしているJavaでSTAXを使用してXMLとXMLイムを解析しよう -

<?xml version="1.0" encoding="UTF-8"?> 
<Macros> 
    <MacroDefinition> 
      <MacroName> 
       <string>Macro1</string> 
      </MacroName> 
    </MacroDefinition> 
</Macros> 

次のように今私は、マクロのクラスを持っている -

public class Macro { 
    private String name; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
    } 

私はまた、私は 'マクロ'クラスのオブジェクトにXMLを変換しようとするパーサークラスがあります。次のようにパーサクラスのスニペットがある -

public class StaxParser { 
    static final String MACRODEFINITION = "MacroDefinition"; 
    static final String MACRONAME = "MacroName"; 
    static final String STRING = "string"; 

    @SuppressWarnings({ "unchecked", "null" }) 
    public List<Item> readMacro(String configFile) { 
     List<Macro> macroList = new ArrayList<Macro>(); 
     try { 
      // First create a new XMLInputFactory 
      XMLInputFactory inputFactory = XMLInputFactory.newInstance(); 
      // Setup a new eventReader 
      InputStream in = new FileInputStream(configFile); 
      XMLEventReader eventReader = inputFactory.createXMLEventReader(in); 
      // Read the XML document 
      Macro macro = null; 

      while (eventReader.hasNext()) { 
       XMLEvent event = eventReader.nextEvent(); 

       if (event.isStartElement()) { 
        StartElement startElement = event.asStartElement(); 
        if (startElement.getName().getLocalPart() == (MACRODEFINITION)) { 
         macro = new Macro(); 

        } 

        if (event.isStartElement()) { 
         if (event.asStartElement().getName().getLocalPart() 
           .equals(MACRONAME)) { 
          Iterator<Attribute> attributes = event 
            .asStartElement().getAttributes(); 
          while (attributes.hasNext()) { 
           Attribute attribute = attributes.next(); 
           if (attribute.getName().toString() 
             .equals(STRING)) { 
            macro.setMacroName(event.asCharacters() 
              .getData()); 
           } 
          } 
          event = eventReader.nextEvent(); 
          continue; 
         } 
        } 
       } 
       // If we reach the end of an item element we add it to the list 
       if (event.isEndElement()) { 
        EndElement endElement = event.asEndElement(); 
        if (endElement.getName().getLocalPart() == (MACRODEFINITION)) { 
         macroList.add(macro); 
        } 
       } 

      } 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (XMLStreamException e) { 
      e.printStackTrace(); 
     } 
     return macroList; 
    } 

} 

直面する問題のイムは、パーサが「MACRONAME」の子ノードを読み取ることができないということです。私が考えているのはgetAttributesなので、動作しないのですが、特定のノードの子ノードを取得するためにどのメソッドを呼び出すべきかを知ることはできません。
これに関するお手伝いがあれば幸いです。
おかげ
p1nG

答えて

2

てMacro1は、XMLの属性ではありませんので、イベント属性が空になることを最初の通知。変更後のコード(私は興味のものとすることができるコードの行を示しているが):

if (event.isStartElement() 
    && event.asStartElement().getName().getLocalPart().equals(STRING)) { 
      if (macro == null) { 
       macro = new Macro(); 
      } 
      macro.setName(eventReader.getElementText()); 
    } 

いくつかのヒント:史上==使用はequalsメソッドを使用して文字列を比較することはありません。完全な実例が必要な場合は、私のソリューションを投稿することができますが、少し複雑です。

2

申し訳ありませんが、あなたのコードには多くの問題があり、コンパイルもしません。

MacroクラスはItemを継承したり実装したりしないため、戻り値の型はList<Macro>である必要があります。

第2に、XMLのスキーマに従い、イベント名の平等性を任意にテストするのではなく、安全な入れ子を保証し、途中でMacroオブジェクトを作成する必要があります。マクロ名以外のデータも取得する予定がある場合は、STRINGイベントが発生していないかどうかを確認するだけで回避できます。

第3に、同じチェックを入れ子にすることは役に立たない。 event.isStartElement()

第四に、あなたは、このようなStaxParserとしてクラス、直接ではなく、ファイル名にSourceまたはReaderまたはStreamを提供する必要がありますが、私はあなたのAPIを壊す避けるために、この変更が含まれていませんでした。

class StaxParser { 
    static final String MACRODEFINITION = "MacroDefinition"; 
    static final String MACRONAME = "MacroName"; 
    static final String STRING = "string"; 

    @SuppressWarnings({ "unchecked", "null" }) 
    public List<Macro> readMacro(final String configFile) { 
     final List<Macro> macroList = new ArrayList<Macro>(); 
     try { 
      // First create a new XMLInputFactory 
      final XMLInputFactory inputFactory = XMLInputFactory.newInstance(); 
      // Setup a new eventReader 
      final InputStream in = new FileInputStream(configFile); 
      final XMLEventReader eventReader = inputFactory.createXMLEventReader(in); 
      // Read the XML document 

      final Template template = getTemplate(eventReader); 
      macroList.addAll(template.process(null, getMacrosProcessor(template))); 

     } catch (final FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (final XMLStreamException e) { 
      e.printStackTrace(); 
     } 
     return macroList; 
    } 

    interface Template { 
     <T> T process(String parent, EventProcessor<T> ep) throws XMLStreamException; 
    } 

    static Template getTemplate(final XMLEventReader eventReader) { 
     return new Template() { 
      @Override 
      public <T> T process(final String parent, final EventProcessor<T> ep) throws XMLStreamException { 
       T t = null; 
       boolean process = true; 
       while (process && eventReader.hasNext()) { 
        final XMLEvent event = eventReader.nextEvent(); 
        if (ep.acceptsEvent(event)) { 
         t = ep.processEvent(event); 
        } 
        if (event.isEndElement()) { 
         if (null != parent && parent.equals(event.asEndElement().getName().getLocalPart())) { 
          process = false; 
         } 
        } 
       } 
       return t; 
      } 
     }; 
    } 

    interface EventProcessor<T> { 
     boolean acceptsEvent(XMLEvent event); 

     T processEvent(XMLEvent event) throws XMLStreamException; 
    } 

    static EventProcessor<List<Macro>> getMacrosProcessor(final Template template) { 
     final List<Macro> macroList = new ArrayList<Macro>(); 
     return new EventProcessor<List<Macro>>() { 
      @Override 
      public boolean acceptsEvent(final XMLEvent event) { 
       return event.isStartElement() 
         && MACRODEFINITION.equals(event.asStartElement().getName().getLocalPart()); 
      } 

      @Override 
      public List<Macro> processEvent(final XMLEvent event) throws XMLStreamException { 
       macroList.add(template.process(MACRODEFINITION, getMacroDefinitionProcessor(template))); 
       return macroList; 
      } 
     }; 
    } 

    static EventProcessor<Macro> getMacroDefinitionProcessor(final Template template) { 
     return new EventProcessor<Macro>() { 
      @Override 
      public boolean acceptsEvent(final XMLEvent event) { 
       return event.isStartElement() && MACRONAME.equals(event.asStartElement().getName().getLocalPart()); 
      } 

      @Override 
      public Macro processEvent(final XMLEvent event) throws XMLStreamException { 
       final Macro macro = new Macro(); 
       macro.setName(template.process(MACRONAME, getMacroNameProcessor(template))); 
       return macro; 
      } 
     }; 
    } 

    static EventProcessor<String> getMacroNameProcessor(final Template template) { 
     return new EventProcessor<String>() { 
      @Override 
      public boolean acceptsEvent(final XMLEvent event) { 
       return event.isStartElement() && STRING.equals(event.asStartElement().getName().getLocalPart()); 
      } 

      @Override 
      public String processEvent(final XMLEvent event) throws XMLStreamException { 
       return template.process(STRING, getStringProcessor()); 
      } 
     }; 
    } 

    static EventProcessor<String> getStringProcessor() { 
     return new EventProcessor<String>() { 
      @Override 
      public boolean acceptsEvent(final XMLEvent event) { 
       return event.isCharacters(); 
      } 

      @Override 
      public String processEvent(final XMLEvent event) throws XMLStreamException { 
       return event.asCharacters().getData(); 
      } 
     }; 
    } 
} 
+1

私は認めなければなりません。あなたがこのコードスニペットで何をしているのかを理解するのにはしばらく時間がかかりましたが、StAXでxmlを解析するためにこれまで見たことのない最良の方法です! – Nerrve

0

あなたが macro.setMacroName変更する必要があります(event.asCharactersを()のgetData());

to macro.setMacroName(attribute.getvalue()。toString());