2013-06-26 3 views
0

У меня есть следующий XML экземпляр:XPath предикаты в условных выражениях

<entities> 
    <person> 
     James 
    </person> 
    <legalEntity legalName="ACME"> 
    </legalEntity> 
    <criminalOrganization> 
     <organizationName>Mafia</organizationName> 
    </criminalOrganization> 
</entities> 

И хотите, чтобы произвести распечатку с типа и имя каждого объекта.

типа это просто имя элемента (person, legalEntity или criminalOrganization), имя определяется по-разному в зависимости от вида объекта.

Поэтому у меня есть следующий код:

XPathExpression expr = xpath.compile("/entities/(person|legalEntity|criminalOrganization)"); 
NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); 
for (int i = 0 ; i < nodes.getLength() ; i++) { 
    Node node = nodes.item(i); 
    String nodeName = node.getNodeName(); 
    XPathExpression exprInner = xpath.compile("text()|@legalName|organizationName/text()"); 
    String name = (String) exprInner.evaluate(node); 
    System.out.printf("node type = %s, name = %s\n", nodeName, name); 
} 

код выводит:

node type = person, name = 
     James 

node type = legalEntity, name = ACME 
node type = criminalOrganization, name = 

Так в основном, название person лиц забирается в порядке (я просто обрезать его) , имя legalEntity также выбрано правильно, но имя criminalOrganization - нет.

После исследования я обнаружил, что это связано с тем, что первое выражение в структуре XPath union: text()|@legalName|organizationName/text() также оценивает (я полагаю, в какой-то пустой строковое значение) в случае criminalOrganization поэтому он возвращается в качестве оцененного значения всего объединенного выражения (а не последнего компонента organizationName/text()).

Мои вопросы:

  1. почему это Mixup не произойдет и в случае legalEntity?

  2. Как включить предикаты имени элемента в выражение XathTime, чтобы гарантировать, что каждый компонент оценивает только для предполагаемого типа. То есть text() для person элементов, @legalName для legalEntity элементов и organizationName/text() для criminalOrganization элементов?

ответ

1

На мой взгляд, ваше решение как-то немного странно, но вы можете попробовать использовать self::.

Попробуйте это (не проверено):

XPathExpression exprInner 
     = xpath.compile("self::person/text()| 
         self::legalEntity/@legalName| 
         self::criminalOrganization/organizationName/text()"); 
+0

Yeap, который работает. Можете ли вы рассказать о том, что странно, и как вы это сделаете по-другому, потому что я новичок в XPath и не знаком с лучшими практиками/обычными шаблонами и т. Д. –

+0

Кроме того, почему я не увидел такое же смешение в случае элемент 'legalEntity'? –

+1

Нет никакого смешивания. Функция 'evaluation()' с вашим выражением возвращает список кивок, узлы находятся в порядке документа (не в порядке вашего выражения, но атрибуты 'legalEntity находятся перед любым текстовым узлом.' '(String)' force to верните только «текст» первого узла. –