Использование целочисленной переменной в выражении XPath Java для извлечения информации из повторяющихся узлов с пространствами имен - PullRequest
1 голос
/ 24 октября 2011

Решено! Спасибо, ребята!

Ваши предложения привели меня к ответу. Так что вы все заслуживаете благодарности за предложение.

Решение для размещения переменной int заключается в следующем:

//Put my xpath into a string variable where it can evaluate my integer "counter"

String myString = "/*[local-name()='root' and namespace-uri()='DK']/*[local-name()='book' and namespace-uri()='DK']" + counter + "]/*[local-name()='item1' and namespace-uri()='DK']/*[local-name()='item2' and namespace-uri()='DK']/*[local-name()='date' and namespace-uri()='DK'][" + counter + "]"


//Then simply put that string variable into the xpath expression.
System.out.print(myString); 

Оригинальный вопрос ниже:

Во-первых, я ценю любую помощь. Заранее спасибо за любую помощь.

У меня есть файл XML, который мне нужно проанализировать.

Скажем, например ...

<root xmlns="DK">
  <book>
    <item1>
      <item2>
        <date>xxx
        </date>
        <date>x1x1x1
        </date>
      </item2>
    </item1>
  </book>
  <book>
    <item1>
      <item2>
        <date>yyy
        </date>
        <date>y1y1y1
        </date>
      </item2>
    </item1>
  </book>    
</root>

Итак, в основном я ищу узел с xxx, а затем перехожу к тому же узлу в следующей книге, содержащей yyy.

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

Я решил попробовать что-то вроде этого.

// I've imported from dom4j SAXreader. I probably could use something different.
import org.dom4j.io.SAXReader;



// Variables
Document document = null;       

// Take input from file    
SAXReader reader = new SAXReader();
document = reader.read("E:/templates/test.xml");

int counter = 0;
int numofbooks = 0;

Element root = document.getRootElement();

for ( Iterator i = root.elementIterator("book"); i.hasNext();) {
    Element element = (Element) i.next();

counter = counter + 1;
numofbooks = counter;
}

System.out.println("There are " + numofbooks + " books required for processing");
while(counter != numofbooks); {
counter = counter + 1;

System.out.print("The values are: ");

// ----- This here is my problem code ----- //
System.out.print(/*[local-name()='root' and namespace-uri()='DK']/*[local-name()='book' and namespace-uri()='DK'][counter]/*[local-name()='item1' and namespace-uri()='DK']/*[local-name()='item2' and namespace-uri()='DK']/*[local-name()='date' and namespace-uri()='DK'][counter]).getStringValue());


System.out.print(" respectively");
}

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

Мое выражение XPath не понимает, что я помещаю переменную "counter", которая является целым числом.

Есть ли какой-нибудь синтаксис, который я могу использовать для этой работы? Или это просто невозможно?

Заранее спасибо.

DK

Ответы [ 3 ]

1 голос
/ 24 октября 2011

Вы можете ссылаться на переменную $counter в своем выражении XPath, и вы можете установить значение переменной из API Java, определив XPathVariableResolver и связав его с XPathFactory.

1 голос
/ 24 октября 2011

Я не вижу в вашем коде вызовов XPath API , просто очень запутанное выражение XPath в комментарии.

Следующий код дает вам NodeList из первого <date> в каждого <item2>:

XPath xpath = XPathFactory.newInstance().newXPath();
NodeList dates = (NodeList) xpath.evaluate("/DK:root/DK:book/DK:item1/DK:item2/DK:date[1]", document, XPathConstants.NODESET);

for (int i = 0; i < dates.getLength(); i++) {
    Node item = dates.item(i);
    String content = item.getTextContent().trim();
    System.err.println(content);
}

С учетом фрагмента XML в вашем вопросе приведенный выше код выведет:

xxx
yyy

Обратите внимание, что XPath начинает считать с 1, поэтому date[1] является первым элементом, а не вторым, как это было бы в Java.

Если вам не нужна осведомленность о пространстве имен, вы можете использовать просто "/root/book/item1/item2/date[1]" (и, вероятно, удалить вызов на DocumentBuilderFactory.setNamespaceAware(true); или эквивалентный)

Если item2 является уникальным во всем документе, вы даже можете уменьшить выражение XPath до "//item2/date[1] "(для осведомленности о NS префикс обоих сегментов пути добавьте DK:, как указано выше).

0 голосов
/ 24 октября 2011

Даже если есть вложенность, которая не известна заранее , можно использовать выражение XPath, например:

(//*[local-name()='root' and namespace-uri()='DK'])[$k]

, где $k можно заменить положительным целым числом.

Запишите :

  1. Необходимы квадратные скобки в вышеприведенном выражении.

  2. Индексированиев XPath основано на 1, а не на 0, как в C # или C ++.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...