2014-11-16 5 views
4

Итак, я работаю над этим проектом в течение последних двух недель, и я не добился этого. Моя проблема заключается не в разборе XML-файла для начала, а в том, что делать с ним впоследствии. Поэтому я сделал программы с SAX, StAX и DOM-парсерами, в которых я беру очень большой XML-файл, а затем распечатываю элементы и их значения в порядке. Однако XML, с которым я имею дело, большой, поэтому использование DOM неэффективно, конечно. Еще одна проблема заключается в том, что файл xml содержит 40 000 записей информации, и его структура сложна. Это немного отрывок из него:XML в структуру данных в java с использованием sax, stax или DOM

<metabolite> 
    <version>3.5</version> 
    <creation_date>2005-11-16 08:48:42 -0700</creation_date> 
    <update_date>2013-02-08 17:07:44 -0700</update_date> 
    <accession>HMDB00002</accession> 
    <secondary_accessions> 
    </secondary_accessions> 
    <name>1,3-Diaminopropane</name> 
    <description>1,3-Diaminopropane is a stable, flammable and highly hydroscopic fluid. It is a polyamine that is normally quite toxic if swallowed, inhaled or absorbed through the skin. It is a catabolic byproduct of spermidine. It is also a precursor in the enzymatic synthesis of beta-alanine. 1, 3-Diaminopropane is involved in the arginine/proline metabolic pathways and the beta-alanine metabolic pathway.</description> 
    <synonyms> 
    <synonym>1,3-Diamino-N-propane</synonym> 
    <synonym>1,3-Propanediamine</synonym> 
    <synonym>1,3-Propylenediamine</synonym> 
    <synonym>1,3-Trimethylenediamine</synonym> 
    <synonym>3-Aminopropylamine</synonym> 
    <synonym>a,w-Propanediamine</synonym> 
    <synonym>Propane-1,3-diamine</synonym> 
    <synonym>Trimethylenediamine</synonym> 
    </synonyms> 
    <chemical_formula>C3H10N2</chemical_formula> 

Так что это один из 40 записей, и она содержит гораздо больше элементов и т.д. в нем. То, что мне нужно, чтобы иметь возможность сделать с моей программой, позволяет пользователю выбирать, какую информацию он хочет от записи 40 000, а затем возвращать информацию в виде листа excel. Поэтому, если я только хотел сказать номер версии и имя для всех 40 000 записей, он вернет только эти значения в excel. В настоящее время я создал программу, которая проходит через StAX и возвращает все элементы и значения через печать на консоль. Как бы я хотел создать структуру данных, например дерево или что-то еще, что позволило бы мне сделать то, что я хочу сделать (т. Е. Пройти через эти данные и вернуть только те данные, которые я ищу).

Это то, что я сделал до сих пор с точки зрения цикла через мой документ и возвращает информацию для того, чтобы 40000 записей:

public class xmlRead { 

    private static XMLStreamReader reader; 

    public xmlRead(){ 

     try{ 

      InputStream file = new FileInputStream("/Users/Kevlar/Dropbox/PhD/Java/HMDB/testOutput.xml"); 
      XMLInputFactory inputFactory = XMLInputFactory.newInstance(); 

      reader = inputFactory.createXMLStreamReader(file); 

      assert(reader.getEventType() == XMLEvent.START_DOCUMENT); 

     } catch (XMLStreamException e){ 
      System.err.println("XMLStreamException : " + e.getMessage()); 

     } catch (FactoryConfigurationError e){ 
      System.err.println("FactoryConfigurationError : " + e.getMessage()); 

     } catch (FileNotFoundException e){ 
      System.err.println("FileNotFoundException : " + e.getMessage()); 

     } 
    } 

    public void metaboliteInfo() throws XMLStreamException{ 

     while(reader.hasNext()){ 

     int event = reader.getEventType(); 

     if(event == XMLStreamConstants.START_ELEMENT && reader.getLocalName() == "metabolite"){ 

      System.out.println("New " + reader.getLocalName());  
      mainElements(reader); 
     } 

     else if(event == XMLStreamConstants.END_DOCUMENT){ 
      System.out.println("end of document"); 
      break; 

     } 

     else{ 

     reader.next(); 

     } 

     } 

     reader.close(); 
    } 


    public void mainElements(XMLStreamReader reader) throws XMLStreamException{ 

      int level = 1; 

      do{ 

       int event = reader.next(); 

       if(event == XMLStreamConstants.START_ELEMENT){ 

        System.out.println("Element :" + reader.getLocalName()); 
        level++; 

        if(level == 2){ 
         subElements(reader); 
         level--; 
        } 
       } 

       else if(event == XMLStreamConstants.CHARACTERS && !reader.isWhiteSpace()){ 
        System.out.println(reader.getText()); 
       } 

       else if(event == XMLStreamConstants.END_ELEMENT){ 
        level--; 
       } 

      }while(level > 0); 

     reader.close(); 

    } 

    private void subElements(XMLStreamReader reader) throws XMLStreamException { 

     int level = 1; 

     do{ 

      int event = reader.next(); 

      if(event == XMLStreamConstants.START_ELEMENT){ 

       System.out.println("Sub element :" + reader.getLocalName()); 
       level++; 

       if(level == 2){ 
        subElements(reader); 
        level--; 
       } 
      } 

      else if(event == XMLStreamConstants.CHARACTERS && !reader.isWhiteSpace()){ 
       System.out.println(reader.getText()); 
      } 

      else if(event == XMLStreamConstants.END_ELEMENT){ 
       level--; 
      } 

     }while(level > 0); 

    reader.close(); 

} 

    public void findElements(XMLStreamReader reader, String element) throws XMLStreamException{ 

      int level = 1; 

      do{ 

       int event = reader.next(); 

       if(event == XMLStreamConstants.START_ELEMENT){ 

        if(reader.getLocalName() == element){ 
         System.out.println(reader.getLocalName()); 
        } 
        level++; 

        if(level == 2){ 
         subElements(reader); 
         level--; 
        } 
       } 

       else if(event == XMLStreamConstants.CHARACTERS && !reader.isWhiteSpace()){ 
        System.out.println(reader.getText()); 
       } 

       else if(event == XMLStreamConstants.END_ELEMENT){ 
        level--; 
       } 

      }while(level > 0); 

     reader.close(); 

    } 


    public static void main(String[] args) throws XMLStreamException{ 

     xmlRead test = new xmlRead(); 
     test.metaboliteInfo(); 

    } 

} 

я, вероятно, следует отметить здесь, что я на самом деле не программист. Мне просто нужно иметь дело с этими файлами XML для целей моих исследований, но у меня нет никого, кто мог бы сделать это для меня, поэтому мои знания о java ограничены. Я боюсь (то есть объяснение вещей в условиях непрофессионала было бы замечательным).

+0

Вы нашли решение для этого? – mobilepotato7

+0

Я сделал, я только что скопировал класс TreeNode из онлайн и, похоже, работал, и я не мог получить то, что другие люди предложили для работы. – user2062207

ответ

4

Посмотрите JAXB. Это основа для преобразования XML в Java-код и наоборот. Если вы используете JXB для автоматического создания ваших классов java для вас, вам не нужно беспокоиться о том, чтобы вручную переместить свою собственную структуру данных.

Вам нужно будет начать с XML-схемы, которая определяет, как будет выглядеть ваш XML-файл. Если у вас его еще нет, вы можете создать файл XML Schema Definition (XSD) из файла XML с помощью такого инструмента, как XMLSpy. JAXB предоставляет инструмент под названием xjc. Это можно использовать для автоматического создания классов Java из схемы XML. Если ваш XML имеет повторяющиеся теги, эти классы Java содержат коллекции, которые можно повторить.

+0

Но можете ли вы написать схему, если файл xml имеет 40 000 записей, для чего записи будут содержать много одинаковых элементов, но в некоторых случаях могут быть разными или иметь больше элементов в определенных областях, чем другие?как и записи, которые у меня есть в файле XML, не соответствуют одному конкретному формату в том смысле, что все они содержат одинаковое количество элементов и типов элементов. – user2062207

+0

Да, например, если один метаболит не имеет синонимов, один синонимы или 100 синонимов , xjc создает класс, в котором класс Metabolite содержит набор синонимов. Эта коллекция синонимов может быть пустой, может содержать один элемент или может содержать 100 элементов в зависимости от того, как выглядит ваша текущая запись Metabolite. – user1717259

+0

Если вы можете создать XSD, вы увидите, что он как можно более ограничительный, хотя он все еще действителен для всех 40000 записей. Ваши автогенерированные классы будут достаточно гибкими, чтобы моделировать все записи. – user1717259

0

XQuery решение. С помощью этого exrpression вы можете фильтровать ввод XML-документ:

declare function local:rewrite($node as node()) as node()? 
{ 
    typeswitch ($node) 
    case element() return 
     if (matches(local-name($node), "(version|name|synonym)")) then 
      element {node-name($node)} 
      { 
       $node/@*, 
       for $child in $node/node() return local:rewrite($child) 
      } 
     else 
      () 
    default return 
     $node 
}; 

for $m in //metabolite 
return <metabolite>{for $c in $m/node() return local:rewrite($c)}</metabolite> 

(version|name|synonym) Заменить с регулярным выражением, совпадающим имена узлов XML, нужно предоставить. Java-7 код, который оценивает выражение XQuery:

import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.InputStream; 
import java.io.OutputStream; 
import javax.xml.transform.sax.SAXSource; 
import javax.xml.transform.stream.StreamResult; 
import net.sf.saxon.Configuration; 
import net.sf.saxon.om.DocumentInfo; 
import net.sf.saxon.query.DynamicQueryContext; 
import net.sf.saxon.query.StaticQueryContext; 
import net.sf.saxon.query.XQueryExpression; 
import org.xml.sax.InputSource; 
// inside a method 
Configuration config = new Configuration(); 
StaticQueryContext sqc = config.newStaticQueryContext(); 
DynamicQueryContext dqc = new DynamicQueryContext(config); 
String xq = "XQUERY_EXPRESSION"; 
try (InputStream xmlFileInput = new FileInputStream("data.xml"); 
     OutputStream xmlFileOutput = new FileOutputStream("data-filtered.xml")) { 
    XQueryExpression expression = sqc.compileQuery(xq); 
    SAXSource source = new SAXSource(new InputSource(xmlFileInput)); 
    DocumentInfo di = config.buildDocument(source); 
    dqc.setContextItem(di); 
    expression.run(dqc, new StreamResult(xmlFileOutput), null); 
} catch (Exception e) { 
    System.err.println(e.getMessage()); 
} 

Saxon (например, saxon9he.jar) библиотека должна присутствовать в пути к классам для того, чтобы скомпилировать и запустить этот код.