2012-03-01 2 views
2

이것은 나에게조차도 어리석은 질문처럼 보일 수 있지만 대답을 찾을 수없는 질문 중 하나입니다.STax를 사용하여 Java에서 XML 구문 분석

임과 같은 모습을 구문 분석하려고 자바 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을 'Macro'클래스의 객체로 변환하려고하는 파서 클래스를 사용한다.

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; 
    } 

} 

문제 메신저 직면 파서가 '매크로 이름'의 자식 노드를 읽을 수 없다는 것이다 - 다음과 같이 파서 클래스 조각입니다. 내 생각에 getAttributes은 작동하지 않게되지만 어떤 특정 노드의 자식 노드를 가져 오기 위해 어떤 메서드를 호출해야하는지에 대한 단서가 없습니다.
이에 대한 도움을 주시면 대단히 감사하겠습니다.
감사
p1nG

답변

2

첫째을 Macro1는 XML 속성 아니라고 통지, 그래서 이벤트 속성은 비어 있습니다. 변경 후 코드 (난 단지 관심이 될 수 있습니다 코드의 라인을 보여준다는) :

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

몇 가지 팁 : 이제까지 == 사용 방법과 동일하여 문자열을 비교하지 않습니다. 전체 예제가 필요하다면 솔루션을 게시 할 수 있지만 좀 더 복잡합니다.

2

죄송하지만, 귀하의 코드에는 많은 문제가 있으며 컴파일도되지 않습니다.

우선 Macro 클래스는 Item을 상속하거나 구현하지 않으므로 반환 유형은 List<Macro>이어야합니다.

둘째, XML의 스키마를 따르고 이벤트 이름이 동일한 지 테스트하지 않고 여기저기서 Macro 개체를 만드는 것이 안전한 네 스팅을 보장해야합니다. 매크로 이름 외에도 다른 데이터를 검색하려는 경우 STRING 이벤트 발생을 확인하는 것만으로도 벗어날 수 없습니다.

셋째, 같은 수표를 중첩하는 것은 쓸모가 없습니다. event.isStartElement().

넷째, 당신은 내가 당신의 API를 파손되지 않도록이 변경을 포함하지 않은 Source 또는 Reader이나하지 직접 StaxParser, 파일 이름과 같은 클래스에 Stream 만 제공해야한다.

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 매크로 .setMacroName (attribute.getvalue(). toString());