2013-10-05 3 views
-1

XML 파일 (소스)을 파싱하고 새 파일 (결과)을 동시에 작성하고 있습니다.XML을 파싱하는 동안 ArrayIndexOutOfBoundsException이 발생했습니다.

<?xml version="1.0"?> 
<poll> 

<pollHead> 
    <code>1</code> 
    <title>Here's the title</title> 
    <description>Desc</description> 
    <author>Hilbert Von Neumann</author> 
    <date>2013-09-15T11:53:00</date> 
</pollHead> 
<pollBody> 
    <topic code="T1"> 
     <topicHead> 
      <title>Topic title bla</title> 
      <description>description bla bla</description> 
     </topicHead> 
     <topicBody> 
       <question code="T1Q1" type="unique">How do you blabla?</question> 
       <option code="T1Q1_1">bla bla</option> 
       <option code="T1Q1_2">ok bla</option> 
       <option code="T1Q1_3">strabla</option> 

       <question code="T1Q2" type="unique">Are they bli bli?</question> 
       <option code="T1Q2_1">Lorem Ipsum</option> 
       <option code="T1Q2_2">Lorem Ipsum2</option> 
       <option code="T1Q2_3">Lorem Ipsum3</option> 

     </topicBody> 
    </topic> 
</pollBody> 
</poll> 

나는이 소스 XML 코드를 분석하고 <answer> 요소의 <option> 요소를 변환하는 새로운 XML을 작성하려는 :

여기에 소스 XML입니다. 그러나 결과 XML에는 code 속성을 가지고있는 요소 인 answer 요소 만 나열되어야하며 그 값은 특정 HashMap에 포함되어 있습니다. 따라서 <option>에 내 HashMap에 포함 된 코드가있는 경우 <option><answer>이됩니다. 그렇지 않으면 결과 XML에 기록되지 않고 삭제되어야합니다. N.B : HashMap의는이 코드를 작성했습니다

아래의 코드에 questionAnswers라고하지만, 나에게는 ArrayIndexOutOfBoundsException를 제공한다. 여기에 코드입니다 :

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

     if (event.getEventType() == XMLEvent.START_ELEMENT && event.asStartElement().getName().getLocalPart().equals("option")) { 

     Iterator ite = event.asStartElement().getAttributes(); 

     while (ite.hasNext()) { 
      Attribute attr = (Attribute) ite.next(); 
      if (attr.getName().getLocalPart().equals("code") && questionAnswers.containsValue(attr.getValue())) { 
      String optionCodeValue = attr.getValue(); 
        writer.add(eventFactory.createStartElement("", null, "answer")); 
      writer.add(eventFactory.createAttribute("code", optionCodeValue)); 
      } 

     } 
      event = xer.nextEvent(); 
     } else { 
     writer.add(event); 
     } 
    } 
writer.close(); 

그리고 여기에 오류 발생 :

javax.xml.stream.XMLStreamException: No element was found to write: java.lang.ArrayIndexOutOfBoundsException: -1 

at com.sun.xml.internal.stream.writers.XMLStreamWriterImpl.writeEndElement(XMLStreamWriterImpl.java:930) 
at com.sun.xml.internal.stream.writers.XMLEventWriterImpl.add(XMLEventWriterImpl.java:186) 
... 

내가 여기에 놓친 거지 무슨 일이? 뭐가 문제 야?

답변

1

잘못된 xml 문서를 만들 때 이러한 오류가 발생합니다.

귀하의 코드를 수정했습니다. 그것이 무엇을하고 있는지 이해하는 주석을보십시오.

import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.Map; 
import javax.xml.stream.XMLEventFactory; 
import javax.xml.stream.XMLEventReader; 
import javax.xml.stream.XMLEventWriter; 
import javax.xml.stream.XMLInputFactory; 
import javax.xml.stream.XMLOutputFactory; 
import javax.xml.stream.XMLStreamException; 
import javax.xml.stream.events.Attribute; 
import javax.xml.stream.events.StartElement; 
import javax.xml.stream.events.XMLEvent; 


public class OptionToAnswer 
{ 
    private static XMLInputFactory inFactory = XMLInputFactory.newInstance(); 
    private static XMLOutputFactory outFactory = XMLOutputFactory.newInstance(); 

    public static void main(String[] args) throws XMLStreamException, IOException 
    { 
    Map<String, String> questionAnswers = new HashMap<String, String>(); 
    questionAnswers.put("foobar12", "T1Q1_2"); 
    questionAnswers.put("foobar23", "T1Q2_3"); 

    XMLEventReader xer = inFactory.createXMLEventReader(new FileInputStream("options.xml")); 
    XMLEventWriter writer = outFactory.createXMLEventWriter(new FileOutputStream("answer.xml")); 
    XMLEventFactory eventFactory = XMLEventFactory.newInstance(); 

    /* 
    need to remember if there is some whitespace like newlines "\n" before <option> start element 
    so that we add it before <answer> element, or ignore it when skipping unmatched option element 
     */ 
    XMLEvent whitespaceBeforeOptionStartElement=null; 


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

     //use peek() to see if <option> element is after whitespace 
     if (event.getEventType() == XMLEvent.CHARACTERS && event.asCharacters().isWhiteSpace() && 
      xer.peek().getEventType() == XMLEvent.START_ELEMENT && xer.peek().asStartElement().getName().getLocalPart().equals("option")) { 

     whitespaceBeforeOptionStartElement = event; 
     } 
     else if (event.getEventType() == XMLEvent.START_ELEMENT && event.asStartElement().getName().getLocalPart().equals("option")) { 

     StartElement optionStartElementEvent = event.asStartElement(); 

     /* 
     In general there can be some other attribute before code attribute. 
     canConvertOptionToAnswer() returns true if "code" attribute value is contained in "questionAnswers" map 
     If there is a match do conversion of <option> to <answer> else skip <option> until </option> 
     */ 
     if(canConvertOptionToAnswer(optionStartElementEvent, questionAnswers)) 
     { 
      convertOptionToAnswer(whitespaceBeforeOptionStartElement, optionStartElementEvent, xer, writer, eventFactory); 
     } 
     else 
     { 
      skipOption(xer); 
     } 

     whitespaceBeforeOptionStartElement=null; 

     } else { 
     writer.add(event); 
     } 
    } 
    writer.close(); 

    } 

    /* 
    Skip everything after <option> until end element: 
     <option> .... </option> 

    Assuming previous event of "XMLEventReader xer" was START_ELEMENT <option> 
    */ 
    private static void skipOption(XMLEventReader xer) throws XMLStreamException 
    { 
    XMLEvent eventWithinOptionElement; 
    do 
    { 
     eventWithinOptionElement = xer.nextEvent(); 
    } 
    while(!(eventWithinOptionElement.getEventType() == XMLEvent.END_ELEMENT && eventWithinOptionElement.asEndElement().getName().getLocalPart().equals("option"))); 
    } 

    private static void convertOptionToAnswer(
     XMLEvent whitespaceBeforeOptionStartElement, StartElement optionStartElementEvent, 
     XMLEventReader xer, 
     XMLEventWriter writer, 
     XMLEventFactory eventFactory) throws XMLStreamException 
    { 
    if(whitespaceBeforeOptionStartElement != null) 
    { 
     writer.add(whitespaceBeforeOptionStartElement); 
    } 

    writer.add(eventFactory.createStartElement("", null, "answer")); 

    /* 
    copy attributes. Note that getAttributes() may not return attributes in the same order as they appear in xml document 
    because according to XML spec order of attributes is not important. 
    */ 
    Iterator ite = optionStartElementEvent.getAttributes(); 
    while(ite.hasNext()) 
    { 
     Attribute attribute = (Attribute) ite.next(); 
     writer.add(attribute); 
    } 

    //copy everything until </option> end element: 
    XMLEvent eventWithinOptionElement = xer.nextEvent(); 
    while(!(eventWithinOptionElement.getEventType() == XMLEvent.END_ELEMENT && eventWithinOptionElement.asEndElement().getName().getLocalPart().equals("option"))) 
    { 
     writer.add(eventWithinOptionElement); 
     eventWithinOptionElement = xer.nextEvent(); 
    } 

    writer.add(eventFactory.createEndElement("", null, "answer")); 
    } 

    private static boolean canConvertOptionToAnswer(StartElement optionStartElementEvent, Map<String, String> questionAnswers) 
    { 
    Iterator ite = optionStartElementEvent.getAttributes(); 

    while (ite.hasNext()) { 
     Attribute attr = (Attribute) ite.next(); 
     if (attr.getName().getLocalPart().equals("code") && questionAnswers.containsValue(attr.getValue())) { 
     return true; 
     } 
    } 

    return false; 

    } 
} 

가정 questionAnswers 값을 T1Q1_2을 가지고 있으며, 이것은 생산 될 것이다 T1Q2_3 :

<?xml version="1.0" encoding="UTF-8"?><poll> 

    <pollHead> 
     <code>1</code> 
     <title>Here's the title</title> 
     <description>Desc</description> 
     <author>Hilbert Von Neumann</author> 
     <date>2013-09-15T11:53:00</date> 
    </pollHead> 
    <pollBody> 
     <topic code="T1"> 
      <topicHead> 
       <title>Topic title bla</title> 
       <description>description bla bla</description> 
      </topicHead> 
      <topicBody> 
       <question code="T1Q1" type="unique">How do you blabla?</question> 
       <answer code="T1Q1_2">ok bla</answer> 

       <question code="T1Q2" type="unique">Are they bli bli?</question> 
       <answer code="T1Q2_3">Lorem Ipsum3</answer> 

      </topicBody> 
     </topic> 
    </pollBody> 
</poll> 
+0

굉장 대답은, 내가 당신 같은 발견되는 사용자 기뻐요. 우수, 감사합니다 :) –

+0

감사. 기쁜 데 도움이되었습니다. –

관련 문제