xPath извлекает несколько значений

У меня есть огромный xml, в котором мне нужно найти сумму для оплаты и соответствующий идентификатор счета.

Я только что понял, как выбрать правильную сумму (расположенную в 2 ячейках от ячейки с CellText = 'amount'). Я могу распечатать это, и это работает.

Теперь мне также нужно распечатать соответствующий billID. Как я могу это сделать?

Это пример типа XML, который я использую:

<Section>
<Item>
    <TableRow>
        <Cell>
           <RowNo>4</RowNo>
           <CellColNo>1</CellColNo>
           <CellText>amount</CellText>
           <CellAttribute/>
        </Cell>
        <Cell>
           <RowNo>4</RowNo>
           <CellColNo>2</CellColNo>
           <CellText/>
           <CellAttribute/>
        </Cell>
        <Cell>
           <RowNo>4</RowNo>
           <CellColNo>3</CellColNo>
           <CellText>138</CellText>
           <CellAttribute/>
        </Cell>
    </TableRow>
</Item>
<Item>
    <BillID>123456</BillID>
</Item>
</Section>
<Section>
...
</Section>

это мой код, где мне нужно добавить, что идентификатор счета также должен быть напечатан:

XPath xPath =  XPathFactory.newInstance().newXPath();
String exprString = "//TableRow/Cell[CellText='amount:']/following-sibling::cell[2]CellText/text()";
XPathExpression expr = xPath.compile(exprString);

    Object result = expr.evaluate(doc, XPathConstants.NODESET);
    NodeList nodes = (NodeList) result;
    for (int j = 0; j < nodes.getLength(); j++) {
        System.out.println(nodes.item(j).getNodeValue());
    }

(Я знаю, что XML не имеет смысла, это просто для иллюстрации формата. Также есть несколько «Разделов», поэтому мне нужно убедиться, что я выбрал правильный!). Заранее спасибо!


person Malin    schedule 29.02.2016    source источник
comment
и, конечно же, есть несколько узловых объектов, так что мне бы очень хотелось выбрать правильный!   -  person Malin    schedule 01.03.2016
comment
Вы должны предпочесть добавлять дополнительную информацию к своему вопросу через правки, а не писать комментарии.   -  person zx485    schedule 01.03.2016
comment
Выполнено! Можете ли вы помочь мне с ответом сейчас, когда вы нашли время, чтобы прокомментировать;)   -  person Malin    schedule 01.03.2016
comment
Нет. Но я могу дать ссылку на этот вопрос SO. Выглядит почти так же, как у вас.   -  person zx485    schedule 01.03.2016
comment
да, но это следующая проблема...   -  person Malin    schedule 01.03.2016


Ответы (2)


Если вы хотите получить оба String, вы можете использовать следующее выражение XPath, применяя оператор объединения узлов | относительно гипотетического узла root:

/root/Section/Item/TableRow/Cell/CellText[text()='amount']/parent::Cell/following-sibling::Cell[2]/CellText/text() | /root/Section/Item/BillID/text()

который можно проверить здесь, в XPathFiddle. Это приводит к

138
123456

person zx485    schedule 29.02.2016

Этот фрагмент сделает это. В узле, где вы выбираете количество, найдите узел-предок Item, перейдите к следующему брату и выберите текст BillID. При этом используется следующий XPath после выбора суммы:

ancestor::Item[1]/following-sibling::Item[1]/BillID/text()

import java.io.StringReader;
import javax.xml.xpath.*;
import org.w3c.dom.*;
import org.xml.sax.InputSource;

public class GetTheBillId {
    private static final String xml1=
"<root>"+
"<Item>"+
"    <TableRow>"+
"        <Cell>"+
"           <RowNo>4</RowNo>"+
"           <CellColNo>1</CellColNo>"+
"           <CellText>amount</CellText>"+
"           <CellAttribute/>"+
"        </Cell>"+
"        <Cell>"+
"           <RowNo>4</RowNo>"+
"           <CellColNo>2</CellColNo>"+
"           <CellText/>"+
"           <CellAttribute/>"+
"        </Cell>"+
"        <Cell>"+
"           <RowNo>4</RowNo>"+
"           <CellColNo>3</CellColNo>"+
"           <CellText>138</CellText>"+
"           <CellAttribute/>"+
"        </Cell>"+
"    </TableRow>"+
"</Item>"+
"<Item>"+
"    <BillID>123456</BillID>"+
"</Item>"+
"</root>";

    private static final String xpathExpr1=
"//TableRow/Cell[CellText='amount']/following-sibling::Cell[2]/CellText/text()";

    private static final String xpathExpr2=
"ancestor::Item[1]/following-sibling::Item[1]/BillID/text()";   

    public static void main(String[] args) {
        try {
            XPath xpath = XPathFactory.newInstance().newXPath();
            XPathExpression expr1 = xpath.compile(xpathExpr1);
            XPathExpression expr2 = xpath.compile(xpathExpr2);
            NodeList nodeList = (NodeList) expr1.evaluate(new InputSource(new StringReader(xml1)),XPathConstants.NODESET);
            StringBuilder sb = new StringBuilder();
            for( int i = 0; i != nodeList.getLength(); ++i ) {
                Node n = (Node) nodeList.item(i);
                sb.append( "Amount=" ).append(n.getNodeValue());

                Node billId = (Node) expr2.evaluate(n,XPathConstants.NODE); // search for Bill ID
                sb.append("; BillId=").append(billId.getNodeValue());
                sb.append(System.lineSeparator());
            }
            System.out.println(sb.toString());
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
    }
}

Выходы:

Amount=138; BillId=123456
person TT.    schedule 29.02.2016