2014-02-13 3 views
2

Input (fullInput)

Представьте я следующее как InputStream (или как String в памяти считываются из этого потока):Как разобрать XML частично (только один уровень глубокий)

<?xml version="1.0" ?> 
<root> 
    <element attr="val1"><x /><y /></element> 
    <element attr="val2"><y /></element> 
    <element attr="val3"><x /><x /></element> 
    <element attr="val4"><z /><y /></element> 
</root> 

Как я хочу использовать решение (bridgeXml)

IProprietaryUnmarshaller UNMARSHALLER = ...; 
List<Element> parseFullXml(String fullInput) throws UnmarshallException { 
    List<String> inputs = bridgeXml(fullInput); 
    List<Element> outputs = new ArrayList(); 
    for(String input : inputs) { 
     Element e = UNMARSHALLER.unmarshall(input); 
     outputs.add(e); 
    } 
    return outputs; 
} 

Что я ищу

Я ищу реализацию/идею для bridgeXml, где вход String/*Stream разбит на маленькие патроны строк, которые являются хорошо сформированными XML-документами (без объявления XML) сами по себе.

тривиальная реализацией Я хочу, чтобы избежать

В приведенных ниже реализации является ошибками, негибким и не должен быть использован, я ищу для надлежащих один с помощью какого-то библиотеки или XML-парсера!

List<String> bridgeXml(String input) { 
    // strip anything up to the opening root element, and LTrim the remainder 
    input = input.replaceAll("(?s)^.*<root.*?>\\s*", ""); 
    // strip anything after the closing root element, and RTrim the remainder 
    input = input.replaceAll("(?s)\\s*</root.*$", ""); 
    // split at </element> closing tags, not removing them (?<= does the magic) 
    return Arrays.asList(input.split("(?<=</element>)")); 
} 

Ограничения

  • Входной XML не может быть изменен, и является полностью действительным XML.
  • Собственный немаршаллер должен использоваться и не может быть изменен.
  • Я ищу решение, в котором файл не XML-маршаллированный, XML-маршаллированный, проприетарный unmarshalled.
  • (Не берите в XML/стиль кода Java, форматирование, видимость модификаторов и т.д.!
    Эти упрощенные коды для облегчения общения.)

Solution (редактировать)

Я закончил написав эту статью ... Я закончил двойной анализ XML (см. getOuterXml), потому что было преждевременно предполагать, что он медленный. После этого у меня есть огромный запрос БД, который медленнее.

protected <T> List<T> read(InputStream inputStream, String tagName) throws XMLStreamException, 
    TransformerException, DecodingException 
{ 
    List<T> result = new ArrayList<T>(); 
    XMLInputFactory xmlFactory = XMLInputFactory.newInstance(); 
    XMLStreamReader xmlReader = xmlFactory.createXMLStreamReader(inputStream, "ISO-8859-1"); 
    while (xmlReader.hasNext()) { 
     xmlReader.next(); 
     if (xmlReader.isStartElement() && tagName.equals(xmlReader.getLocalName())) { 
      String output = getOuterXml(xmlReader); 
      @SuppressWarnings("unchecked") 
      T object = (T) UNMARSHALLER.unmarshall(output); 
      result.add(object); 
     } 
    } 
    return result; 
} 

protected String getOuterXml(XMLStreamReader xmlr) throws TransformerException 
{ 
    Transformer transformer = TransformerFactory.newInstance().newTransformer(); 
    StringWriter stringWriter = new StringWriter(); 
    transformer.transform(new StAXSource(xmlr), new StreamResult(stringWriter)); 
    return stringWriter.toString(); 
} 

protected <T> List<T> getObjects(String urlString, String tagName) 
{ 
    LOG.info("Downloading [{}] updates from [{}].", tagName, urlString); 
    HttpURLConnection conn = null; 
    InputStream inputStream = null; 
    try { 
     URL url = new URL(urlString); 
     conn = (HttpURLConnection) url.openConnection(); 
     conn.connect(); 
     inputStream = conn.getInputStream(); 
     return read(inputStream, tagName); 
    } catch (Exception ex) { 
     String exceptionMessage = "Updating [" + tagName + "] from [" + urlString + "] failed."; 
     LOG.error(exceptionMessage, ex); 
     throw new MyFancyWrapperException(exceptionMessage, ex); 
    } finally { 
     if (inputStream != null) { 
      try { 
       inputStream.close(); 
      } catch (IOException ex) { 
       LOG.warn("Cannot close HTTP's input stream", ex); 
      } 
     } 
     if (conn != null) { 
      conn.disconnect(); 
     } 
    } 
} 
+0

Вы уже помечено свой вопрос с StAX. То, что я вам предлагаю. С его помощью вы можете передавать XML-документы или их части и использовать JAXB для синтаксического анализа действительного югу от xml. Вот что я уже делаю, чтобы разделить очень большие XML-документы с некоторыми интересными частями для unmarshaller. – wumpz

ответ

1

Так вот Литт StAX анализатор для примера XML:

String xml = "<root><element>test</element></root>"; 
XMLInputFactory xmlif = XMLInputFactory.newInstance(); 
XMLStreamReader xmlr = xmlif.createXMLStreamReader(new StringReader(xml)); 
while (xmlr.hasNext()) { 
    xmlr.next(); 
    if (xmlr.isStartElement() || xmlr.isEndElement()) { 
     System.out.println(xmlr.getLocalName() + " " + xmlr.getEventType()); 
    } 
} 

и здесь вы найдете объяснение, как вы могли бы объединить StAX с JAXB.

http://blog.bdoughan.com/2012/08/handle-middle-of-xml-document-with-jaxb.html

+0

Спасибо, это звучит правильно, я дам ему попробовать завтра! – TWiStErRob

Смежные вопросы