2015-04-02 6 views
0

Я пытаюсь разобрать XML на Java с помощью SAX. По этой причине я сделал себе UnitTest.XML не может быть проанализирован, когда String, без проблем при анализе из файла

Когда я пытаюсь разобрать XML из файла, все работает замечательно, но когда я пытаюсь разобрать тот же XML из строки синтаксические терпит неудачу и дает мне следующую ошибку:

java.net.MalformedURLException: no protocol: <?xml version="1.0" encoding="UTF-8"?> 
<root>          
    <subnode>        
     <id>s1</id>       
     <name>Subnode one</name>   
     <value>11</value>     
    </subnode>        
    <subnode>        
     <id>s2</id>       
     <name>Subnode two</name>   
     <value>22</value>     
    </subnode>        
</root>         
    at java.net.URL.<init>(URL.java:586) 
    at java.net.URL.<init>(URL.java:483) 
    at java.net.URL.<init>(URL.java:432) 
    at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:619) 
    at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:189) 
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:812) 
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777) 
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) 
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213) 
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:649) 
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(SAXParserImpl.java:333) 
    at javax.xml.parsers.SAXParser.parse(SAXParser.java:274) 
    at tests.xmlparsing.XMLParserTest.ParseStringTest(XMLParserTest.java:89) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:157) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74) 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134) 

Моему UnitTest-файл: http://pastebin.com/vd2zjWHu

package tests.xmlparsing; 

import org.junit.Test; 
import org.xml.sax.Attributes; 
import org.xml.sax.SAXException; 
import org.xml.sax.helpers.DefaultHandler; 

import java.io.*; 
import java.util.LinkedList; 
import java.util.List; 
import javax.xml.parsers.*; 

import static org.junit.Assert.*; 

/** 
* Created by simonlammer on 14.03.15. 
*/ 
public class XMLParserTest { 
    private static SAXHandler handler; 
    private static String xmlString; 
    static { 
     handler = new SAXHandler(); 
     xmlString = 
      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "\r\n" + 
      "<root>         " + "\r\n" + 
      " <subnode>        " + "\r\n" + 
      "  <id>s1</id>      " + "\r\n" + 
      "  <name>Subnode one</name>   " + "\r\n" + 
      "  <value>11</value>     " + "\r\n" + 
      " </subnode>        " + "\r\n" + 
      " <subnode>        " + "\r\n" + 
      "  <id>s2</id>      " + "\r\n" + 
      "  <name>Subnode two</name>   " + "\r\n" + 
      "  <value>22</value>     " + "\r\n" + 
      " </subnode>        " + "\r\n" + 
      "</root>         "; 
    } 
    private SAXParser parser; 

    public XMLParserTest() throws ParserConfigurationException, SAXException { 
     this.parser = newSAXParser(); 
    } 

    private SAXParser newSAXParser() throws ParserConfigurationException, SAXException { 
     SAXParserFactory factory = SAXParserFactory.newInstance(); 
     SAXParser parser = factory.newSAXParser(); // throws ParserConfigurationException 
     return parser; 
    } 

    @Test 
    public void SAXParserNotNullTest() { 
     assertNotNull(parser); 
    } 

    @Test 
    public void SAXHandlerNotNullTest() { 
     assertNotNull(handler); 
    } 

    @Test 
    public void ParseFileTest() throws IOException, SAXException { 
     // create File 
     File file = new File("temporaryXMLFileUsedForUnitTest.xml"); 
     try { 
      FileWriter fw = new FileWriter(file); 
      fw.write(xmlString); 
      fw.flush(); 
      fw.close(); 
     } catch (IOException e) { 
      fail("Could not create file"); 
     } 

     // parse 
     handler.clearElements(); 
     parser.parse(file, handler); 
     List<SampleElement> elements = handler.getElements(); 

     // validate 
     validateElementList(elements); 

     // delete file 
     file.delete(); 
    } 

    @Test 
    public void ParseStringTest() throws IOException, SAXException { 
     // parse 
     handler.clearElements(); 
     parser.parse(xmlString, handler); 
     List<SampleElement> elements = handler.getElements(); 

     // validate 
     validateElementList(elements); 
    } 

    private void validateElementList(List<SampleElement> elements) { 
     assertEquals(2,    elements.size()); 
     assertEquals("s1",   elements.get(0).getId()); 
     assertEquals("Subnode one", elements.get(0).getName()); 
     assertEquals(11,   elements.get(0).getValue()); 
     assertEquals("s2",   elements.get(1).getId()); 
     assertEquals("Subnode two", elements.get(1).getName()); 
     assertEquals(22,   elements.get(1).getValue()); 
    } 

    public static class SampleElement { 
     private String id; 
     private String name; 
     private int value; 

     public SampleElement(String id, String name, int value) { 
      this.id = id; 
      this.name = name; 
      this.value = value; 
     } 

     public String getId() { 
      return id; 
     } 

     public String getName() { 
      return name; 
     } 

     public int getValue() { 
      return value; 
     } 
    } 

    public static class SAXHandler extends DefaultHandler { 
     private LinkedList<SampleElement> elements; 
     private String id; 
     private String name; 
     private boolean tagId = false; 
     private boolean tagName = false; 
     private boolean tagValue = false; 
     private String value; 

     public SAXHandler() { 
      elements = new LinkedList<>(); 
     } 

     public void clearElements() { 
      elements.clear(); 
     } 

     @Override 
     public void characters(char[] ch, int start, int length) throws SAXException { 
      String str = new String(ch, start, length); 
      if (tagId) { 
       id = str; 
      } else if (tagName) { 
       name = str; 
      } else if (tagValue) { 
       value = str; 
      } 
     } 

     public List<SampleElement> getElements() { 
      return (LinkedList<SampleElement>) elements.clone(); 
     } 

     @Override 
     public void endElement(String uri, String localName, String qName) throws SAXException { 
      if (qName.equalsIgnoreCase("id")) { 
       tagId = false; 
      } else if (qName.equalsIgnoreCase("name")) { 
       tagName = false; 
      } else if (qName.equalsIgnoreCase("value")) { 
       tagValue = false; 

       // create new SampleElement 
       if (id != null && name != null && value != null) { 
        int val = Integer.parseInt(value); 
        SampleElement element = new SampleElement(id, name, val); 
        elements.add(element); 

        // clear strings 
        id = name = value = null; 
       } 
      } 
     } 

     @Override 
     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { 
      if (qName.equalsIgnoreCase("id")) { 
       tagId = true; 
       id = null; 
      } else if (qName.equalsIgnoreCase("name")) { 
       tagName = true; 
       name = null; 
      } else if (qName.equalsIgnoreCase("value")) { 
       tagValue = true; 
       value = null; 
      } 
     } 
    } 
} 

Вопрос: Почему это работает при разборе из файла, но не при разборе из строки? Как выполнить синтаксический анализ из строки с помощью анализатора SAX без получения этой ошибки?

Редактировать: Решение было найдено RealSkeptic, спасибо вам большое. Перегрузкой, которую я использовал, не должен был быть сам XML, а скорее путь к XML-файлу. Чтобы решить проблему, мне пришлось изменить «parser.parse (xmlString), обработчик);» на «parser.parse» (новый InputSource (новый StringReader (xmlString)), обработчик);

ответ

3

используется

parser.parse(xmlString, handler); 

Но documentation из SAXParser.parse(String uri,DefaultHandler dh) ясно говорит о том, что строка передать это URI от того, где XML на самом деле. Это не сам XML!

Если вы хотите прочитать XML непосредственно из строки, вам необходимо создать InputSource из строки, а затем использовать метод SAXParser.parse(InputSource is,DefaultHandler dh).

Чтобы создать InputSource из String, вы можете использовать

InputSource is = new InputSource(new StringReader(xmlString)); 

StringReader это особый тип Reader, который считывает из строки (так же, как это было бы от InputStream).