Обработка иерархического XML-документа с помощью XPATH в Java. Эффективность?

Варианты этого вопроса уже задавались здесь несколько раз, но мой вопрос больше относится к общей эффективности использования XPATH в Java.

Моя задача: взять статьи в Википедии о географических местоположениях и создать из них иерархическую структуру данных.

Я уже получил XML-версии вики-страниц и переформатировал их в соответствии со схемой, которая имеет интуитивный смысл. Я также сделал серию очень простых классов, представляющих различные уровни административной иерархии, например:

public class Province implements java.io.Serializable {

private ArrayList<City> cities = new ArrayList<City>();
private String hanzi;
private String pinyin;


public Province(String hanzi, String pinyin) {
this.hanzi = hanzi;
this.pinyin = pinyin;
}

А также метод добавления городов, некоторые методы получения и установки, а также метод toString().

Вот пример типа XML-файла, с которым я имею дело:

<mediawiki>
     <page>
           <title>Tianjin</title>
           <revision>
                    <id>2064019</id>
                    <text xml:space="preserve">
                              <province>
                                       <hanzi>天津</hanzi>
                                       <pinyin>Tianjin</pinyin>

                                       <Level2>
                                               <hanzi>和平</hanzi>
                                               <pinyin>Heping</pinyin>
                                               <zip>300000</zip>
                                       </Level2>

                                       <Level2>
                                                <hanzi>河东</hanzi>
                                                <pinyin>Hedong</pinyin>
                                                <zip>300000</zip>
                                        </Level2>

                                </province>
                    </text>
            </revision>
      </page>

...

</mediawiki>

У меня по сути есть функциональная настройка на данный момент, но код является чрезвычайно повторяющимся и не учитывает внутреннюю иерархическую природу географических данных. В идеале я мог бы остановиться на определенном уровне (скажем, "сосредоточиться" на конкретной провинции) и относиться к вещам только в относительных терминах, начиная с этого момента, чтобы минимизировать количество попыток сканирования всего документа. В качестве примера (обратите внимание, я использую абстракцию поверх традиционной установки Document, но методы, приведенные ниже, почти точно соответствуют традиционным методам):

XPathReader reader = new XPathReader("sourceXML\\Provinces.xml");           
String expression = "/mediawiki/page";
NodeList allProvinces = (NodeList)reader.read(expression, XPathConstants.NODESET);

for(int i=0; i < allProvinces.getLength(); i++) {
     expression = "/mediawiki/page[" + i + "]/revision/text/province/hanzi";
     String hanzi = reader.read(expression, XPathConstants.STRING).toString();

     expression = "/mediawiki/page[" + i + "]/revision/text/province/pinyin";
     String pinyin = reader.read(expression, XPathConstants.STRING).toString();

     Province currProv = new Province(hanzi, pinyin);         



     expression = "/mediawiki/page[" + i + "]/revision/text/province/Level2";
     NodeList level2 = (NodeList)reader.read(expression, XPathConstants.NODESET);

     for(int j=1; j < level2.getLength(); j++) {
           expression = "/mediawiki/page[" + i + "]/revision/text/province/Level2[" + j + "]/hanzi";
           String hanzi2 = reader.read(expression, XPathConstants.STRING).toString();   

           expression = "/mediawiki/page[" + i + "]/revision/text/province/Level2[" + j + "]/pinyin";
           String pinyin2 = reader.read(expression, XPathConstants.STRING).toString();  

         City currCity = new City(hanzi2, pinyin2);
         currProv.add(currCity);
...
     }
}   

Откровенно говоря, это кажется глупым. Я не принимаю во внимание тот факт, что все в этих строках идентично, когда я поднимаюсь на уровень, который меня интересует. Я не ссылаюсь ни на какой относительный путь, и всякий раз, когда я пересекаю часть документа, я фактически пересекаю всю вещь. Было бы здорово, если бы я мог на время заблокировать остальную часть исходного XML-документа и сосредоточиться только на своей провинции, ссылаясь на все в дальнейшем с относительной точки зрения.

Особо следует отметить, насколько дорого это стоит за абстракцией "читать":

xPath.compile(expression);
String result = xPathExpression.evaluate (xmlDocument, returnType);

Я по существу перекомпилирую идентичный шаблон с немного другим окончанием? Как насчет загрузки интересующей части, а затем обращения к ее дочерним элементам с помощью чего-то вроде "currProv/hanzi"?

Я рассмотрел другие методы синтаксического анализа XML, и "Digester", кажется, делает что-то похожее на то, что я хочу http://commons.apache.org/digester/core.html, но у меня уже есть почти все в этом XPATH реализация.

У меня есть ноющее подозрение, что решение этой проблемы очень простое... но я не могу понять это решение. Во всяком случае, я благодарю вас за ваше время!

1 ответ

Решение

Относительные вложенные XPath - это путь.

Я возглавляю реализацию EclipseLink JAXB (MOXy), и мы предлагаем эту возможность через аннотацию @XmlPath. Если у вас уже есть XPath, это было бы относительно простым отображением.

Для получения дополнительной информации см.:

Другие вопросы по тегам