2014-02-21 2 views
0

Я следующее (очень большой => 5ГБ) XML:Fetch XML-узлов с помощью Path

<Hotels> 
    <Hotel> 
    <Name>Hotel 1</Name> 
    <City>City 1</City> 
    <Phone>12345</Phone> 
    </Hotel> 
    <Hotel> 
    <Name>Hotel 2</Name> 
    <City>City 2</City> 
    <Phone>67890</Phone> 
    </Hotel> 
    ... 
</Hotels> 

И у меня есть файл, который определяет, какие поля я хочу, чтобы извлечь и то, что их путь:

$root = "/Hotels/Hotel"; 
$fields = array("HotelName" => "/Name", 
       "PhoneNumber" => "/Phone"); 

Таким образом, путь для HotelName будет: /Hotels/Hotel/Name.

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

Как решить эту проблему с помощью путей, без классов и с низким использованием памяти (=> больших файлов)?

// Редактировать: все реализовано. Мне просто нужен способ итерации через Hotel и получить их значения с помощью путей, которые у меня есть.

+1

Для «очень больших» (насколько это возможно?) XML-файлов, которые вы, возможно, захотите рассмотреть, чтобы сбрасывать их в реляционную базу данных (кажется, что этот XML-файл фактически представляет собой таблицу) или использование родного XML-база данных, например [Basex] (http://www.basex.org). –

+0

Насколько велики эти файлы? – user1121883

+0

Файлы могут быть размером 5 ГБ. Я экспортирую их в csv, поэтому я могу импортировать их в MySQL с помощью «LOAD DATA INFILE». – halloei

ответ

0

Попробуйте прочитать этот урок, есть некоторые объяснения и примеры. http://viralpatel.net/blogs/java-xml-xpath-tutorial-parse-xml/

Для вашей порции вы используете Shoudl что-то из семейства Stax, а не DOM.

попробовать сделать это

public class QueryXML { 
    public void query() throws ParserConfigurationException, SAXException, 
     IOException, XPathExpressionException { 
    // standard for reading an XML file 
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
    factory.setNamespaceAware(true); 
    DocumentBuilder builder; 
    Document doc = null; 
    XPathExpression expr = null; 
    builder = factory.newDocumentBuilder(); 
    doc = builder.parse("person.xml"); 

    // create an XPathFactory 
    XPathFactory xFactory = XPathFactory.newInstance(); 

    // create an XPath object 
    XPath xpath = xFactory.newXPath(); 

    // compile the XPath expression 
    expr = xpath.compile("//person[firstname='Lars']/lastname/text()"); 
    // run the query and get a nodeset 
    Object result = expr.evaluate(doc, XPathConstants.NODESET); 

    // cast the result to a DOM NodeList 
    NodeList nodes = (NodeList) result; 
    for (int i=0; i<nodes.getLength();i++){ 
     System.out.println(nodes.item(i).getNodeValue()); 
    } 

    // new XPath expression to get the number of people with name Lars 
    expr = xpath.compile("count(//person[firstname='Lars'])"); 
    // run the query and get the number of nodes 
    Double number = (Double) expr.evaluate(doc, XPathConstants.NUMBER); 
    System.out.println("Number of objects " +number); 

    // do we have more than 2 people with name Lars? 
    expr = xpath.compile("count(//person[firstname='Lars']) >2"); 
    // run the query and get the number of nodes 
    Boolean check = (Boolean) expr.evaluate(doc, XPathConstants.BOOLEAN); 
    System.out.println(check); 
    } 

Вы можете просто адаптировать этот код для ваших нужд.

+0

Вы говорите мне не использовать DOM, и вы отправляете ссылку и код с примерами DOM ..!? – halloei

0

Если вы уже нашли узел <Hotel/> и получили его как DOM-ссылку, просто получите доступ к своим детям (с отелем в качестве контекста). Либо с помощью

  • XPath: ./Name или короче Name (только не запускайте с /, который относится к корню), но убедитесь, что использовать узел в гостинице в качестве контекста запроса; или
  • DOM: hotel.getChildNodes(), а затем проведите цикл по набору результатов, сравнивая имена элементов, чтобы найти соответствующий дочерний узел.
+0

Спасибо, но я не могу сначала создать документ всего файла. Он слишком большой, чтобы загрузить его в память. – halloei

+0

Если вы имеете дело с большими документами XML, рассмотрите возможность использования базы данных XML, специально написанной для этого. [BaseX] (http://basex.org) и [eXist DB] (http://existdb.org) - это примеры с открытым исходным кодом, которые также могут быть связаны с Java. Несколько крутая кривая обучения (это помогает, если вы уже знаете XPath), но стоит усилий. В противном случае вы будете придерживаться сканирования документа с помощью SAX-подобного подхода. –

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