2009-07-15 9 views
21

मुझे संभावित रूप से बड़ी एक्सएमएल फाइलों को पार्स करने की ज़रूरत है, जिनमें से कई एक्सएसडी फाइलों में स्कीमा पहले से ही उपलब्ध कराई गई है, इसलिए एक्सएमएल बाध्यकारी अत्यधिक अनुकूल है। मैं जानना चाहता हूं कि क्या मैं फाइलों को पार्स में पार्स करने के लिए जेएक्सबी का उपयोग कर सकता हूं और यदि ऐसा है, तो कैसे।क्या करक्स में बड़ी एक्सएमएल फाइलों को पार्स कर सकते हैं

उत्तर

17

यह user guide में विस्तृत है। http://jaxb.java.net/ से जेएक्सबी डाउनलोड एक समय में एक खंड को कैसे पार्स करने का एक उदाहरण शामिल है।

जब एक दस्तावेज़ बड़ी है, यह आमतौर पर दोहराए उस में भागों है क्योंकि है। शायद यह लाइन लाइनों की एक बड़ी सूची, के साथ एक खरीद है या शायद यह बड़ी संख्या में लॉग प्रविष्टियों के साथ एक एक्सएमएल लॉग फ़ाइल है।

इस तरह का एक्सएमएल खंड-प्रसंस्करण के लिए उपयुक्त है; मुख्य विचार स्टैक्स एपीआई का उपयोग करें, लूप चलाएं, और अनमर्शल व्यक्तिगत भाग अलग से करें। आपका प्रोग्राम एकल खंड पर कार्य करता है, और फिर इसे फेंक देता है। इस तरह, आप केवल मेमोरी में सबसे अधिक हिस्सा रखेंगे, जो आपको बड़े दस्तावेज़ों को संसाधित करने की अनुमति देता है।

ऐसा करने के तरीके के बारे में अधिक के लिए JAXB आरआई वितरण में स्ट्रीमिंग-unmarshalling उदाहरण और आंशिक-unmarshalling उदाहरण देखें। स्ट्रीमिंग-unmarshalling उदाहरण एक लाभ यह है कि मनमाना घोंसला स्तर पर हिस्सा संभाल कर सकते हैं है, फिर भी ऐसा करना आवश्यक हो आप पुश मॉडल से निपटने के लिए --- JAXB unmarshaller आप और आप के लिए "धक्का" नए हिस्सा होगा ' आपको की आवश्यकता होगी, उन्हें वहां पर संसाधित करें।

इसके विपरीत, आंशिक-unmarshalling उदाहरण एक पुल मॉडल (जो आमतौर पर आसान प्रसंस्करण करता है), में काम करता है लेकिन इस दृष्टिकोण अन्य डेटा बाइंडिंग भागों में कुछ सीमाएं से हिस्सा दोहराया है।

+0

ठीक है, यह शोध करते समय मुझे मिली साइटों में से एक है, लेकिन मैं धारा 5.1.1 में संदर्भित "स्ट्रीमिंग-अनमरशलिंग" और "आंशिक-अनमर्शलिंग" उदाहरणों को ढूंढने में असमर्थ था। –

+7

विषम। तुम कहाँ देख रहे हो? मैंने jaxb.dev.java.net/2.1.12 से JAR को अभी डाउनलोड किया है, इसे अनपॅक किया है, और वहां "नमूने" के तहत "आंशिक-अनारशलिंग" और "स्ट्रीम-अनमारशलिंग" है। – skaffman

24

क्योंकि कोड मायने रखता है, यहां PartialUnmarshaller है जो भाग में एक बड़ी फ़ाइल पढ़ता है। ऐसा नहीं है कि जिस तरह से new PartialUnmarshaller<YourClass>(stream, YourClass.class)

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 
import javax.xml.bind.Unmarshaller; 
import javax.xml.stream.*; 
import java.io.InputStream; 
import java.util.List; 
import java.util.NoSuchElementException; 
import java.util.stream.Collectors; 
import java.util.stream.IntStream; 

import static javax.xml.stream.XMLStreamConstants.*; 

public class PartialUnmarshaller<T> { 
    XMLStreamReader reader; 
    Class<T> clazz; 
    Unmarshaller unmarshaller; 

    public PartialUnmarshaller(InputStream stream, Class<T> clazz) throws XMLStreamException, FactoryConfigurationError, JAXBException { 
     this.clazz = clazz; 
     this.unmarshaller = JAXBContext.newInstance(clazz).createUnmarshaller(); 
     this.reader = XMLInputFactory.newInstance().createXMLStreamReader(stream); 

     /* ignore headers */ 
     skipElements(START_DOCUMENT, DTD); 
     /* ignore root element */ 
     reader.nextTag(); 
     /* if there's no tag, ignore root element's end */ 
     skipElements(END_ELEMENT); 
    } 

    public T next() throws XMLStreamException, JAXBException { 
     if (!hasNext()) 
      throw new NoSuchElementException(); 

     T value = unmarshaller.unmarshal(reader, clazz).getValue(); 

     skipElements(CHARACTERS, END_ELEMENT); 
     return value; 
    } 

    public boolean hasNext() throws XMLStreamException { 
     return reader.hasNext(); 
    } 

    public void close() throws XMLStreamException { 
     reader.close(); 
    } 

    void skipElements(int... elements) throws XMLStreamException { 
     int eventType = reader.getEventType(); 

     List<Integer> types = asList(elements); 
     while (types.contains(eventType)) 
      eventType = reader.next(); 
    } 
} 
+0

मुझे XMLStreamConstants.START_DOCUMENT का उपयोग करने की आवश्यकता है और इस पर काम करने के लिए। –

+0

@MththiasWuttke आप उन्हें एक स्थिर आयात के रूप में जोड़ सकते हैं। आयात स्थिर javax.xml.stream.XMLStreamConstants। *; –

+1

आपको Guava's Ints.asList या java8 IntStream.of (तत्व) .boxed() में भी एकत्रित करने की आवश्यकता हो सकती है (collect.toList()); –

2

यवेस Amsellem का जवाब बहुत अच्छा है इस्तेमाल किया जा सकता है, लेकिन तभी काम करता है सभी तत्वों को ठीक उसी प्रकार के हैं। अन्यथा आपका unmarshall एक अपवाद फेंक देगा, लेकिन पाठक पहले से ही बाइट्स खा लिया होगा, तो आप ठीक करने में असमर्थ होंगे। इसके बजाय, हमें स्काफमैन की सलाह का पालन करना चाहिए और जेएक्सबी जार से नमूना देखना चाहिए।

यह कैसे काम करता व्याख्या करने के लिए:

  1. एक JAXB unmarshaller बनाएँ।
  2. उचित तत्वों को रोकने के लिए unmarshaller में श्रोता जोड़ें। यह सुनिश्चित करने के लिए कि तत्वों को अनारक्षित होने के बाद स्मृति में संग्रहीत नहीं किया जाता है, यह सुनिश्चित करने के लिए ArrayList "हैकिंग" द्वारा किया जाता है।
  3. एक SAX पार्सर बनाएं। यह वह जगह है जहां स्ट्रीमिंग होती है।
  4. SAX पार्सर के लिए हैंडलर उत्पन्न करने के लिए unmarshaller का उपयोग करें।
  5. स्ट्रीम!

मैंने जेनेरिक * के समाधान को संशोधित किया। हालांकि, इसे कुछ प्रतिबिंब की आवश्यकता है। यदि यह ठीक नहीं है, तो कृपया जेएक्सबी जार में कोड नमूने देखें।

ArrayListAddInterceptor.java

import java.lang.reflect.Field; 
import java.util.ArrayList; 

public class ArrayListAddInterceptor<T> extends ArrayList<T> { 
    private static final long serialVersionUID = 1L; 

    private AddInterceptor<T> interceptor; 

    public ArrayListAddInterceptor(AddInterceptor<T> interceptor) { 
     this.interceptor = interceptor; 
    } 

    @Override 
    public boolean add(T t) { 
     interceptor.intercept(t); 
     return false; 
    } 

    public static interface AddInterceptor<T> { 
     public void intercept(T t); 
    } 

    public static void apply(AddInterceptor<?> interceptor, Object o, String property) { 
     try { 
      Field field = o.getClass().getDeclaredField(property); 
      field.setAccessible(true); 
      field.set(o, new ArrayListAddInterceptor(interceptor)); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

} 

Main.java

public class Main { 
    public void parsePurchaseOrders(AddInterceptor<PurchaseOrder> interceptor, List<File> files) { 
     try { 
      // create JAXBContext for the primer.xsd 
      JAXBContext context = JAXBContext.newInstance("primer"); 

      Unmarshaller unmarshaller = context.createUnmarshaller(); 

      // install the callback on all PurchaseOrders instances 
      unmarshaller.setListener(new Unmarshaller.Listener() { 
       public void beforeUnmarshal(Object target, Object parent) { 
        if (target instanceof PurchaseOrders) { 
         ArrayListAddInterceptor.apply(interceptor, target, "purchaseOrder"); 
        } 
       } 
      }); 

      // create a new XML parser 
      SAXParserFactory factory = SAXParserFactory.newInstance(); 
      factory.setNamespaceAware(true); 
      XMLReader reader = factory.newSAXParser().getXMLReader(); 
      reader.setContentHandler(unmarshaller.getUnmarshallerHandler()); 

      for (File file : files) { 
       reader.parse(new InputSource(new FileInputStream(file))); 
      } 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 
} 

* इस कोड का परीक्षण नहीं किया गया है और निदर्शी प्रयोजनों के लिए ही है।

संबंधित मुद्दे

 संबंधित मुद्दे