2013-10-05 87 views
-1

我正在解析XML文件(源代码)并同时写入新文件(结果)。解析XML时ArrayIndexOutOfBoundsException异常

这里的源XML:

<?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代码,写一个新的XML转换中<answer>元素<option>元素。但是结果xml应该只列出answer元素,它们具有code属性,其值包含在特定的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_2T1Q2_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

谢谢。很高兴帮助。 –