2015-07-03 4 views
1

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

<objects count="1"> 
    <object> 
     <stuff>...</stuff> 
     <more_stuff>...</more_stuff> 
     ... 
     <connections> 
      <connection>124</connection> 
      <connection>128</connection> 
     </connections> 
    </object> 
<objects> 

Мне нужно найти целые числа, хранящиеся в <connection> атрибутов. Тем не менее, я не могу гарантировать, что всегда будет ровно два (может быть только один или ничего). Более того, будут случаи, когда элемент <connections> отсутствует.

Я рассматривал такие примеры, как this, но в нем не упоминается, как обращаться с случаями, когда родитель не существует.

В случае, когда <connections> не существует вообще, довольно редко (но это то, что я определенно должен знать, когда это произойдет), и случай, когда он существует, но содержит менее двух <connection>, будет даже реже (в основном я ожидаю, что этого никогда не произойдет).

Должен ли я предположить, что все на месте, и поймать исключение, если что-то произойдет, или есть умный способ обнаружить наличие <connections>?

Моя первоначальная идея состояла в том, чтобы использовать что-то вроде:

InputStream response = urlConnection.getInputStream(); 

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
DocumentBuilder db = dbf.newDocumentBuilder(); 
Document doc = db.parse(response); 

String xPathExpressionString = "/objects/object/connections/connection"; 

XPathFactory xPathFactory = XPathFactory.newInstance(); 
XPath xPath = xPathFactory.newXPath(); 
XPathExpression expr = xPath.compile(xPathExpressionString); 

NodeList nodeList = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); 

for (int i = 0; i < nodeList.getLength(); i++) { 
    Node intersectionNode = nodeList.item(i); 
    if (intersectionNode.getNodeType() == Node.ELEMENT_NODE) { // What is this anyway? 
     // Do something with value 
    } 
} 

Согласно примеру, указанному выше, это должно обработать случай с различными количествами <connection>-х, но как я должен иметь дело с <connections> отсутствует alltoghether.

(Кстати, там всегда должно быть только один object, поэтому нет необходимости беспокоиться о том, что)

ответ

1

Используйте это выражение XPath:

"//object//connection" 

"//" конструкция является краткой формой для "самой-или-потомки" оси. Таким образом, выражение выше выберет все элементы <connection>, у которых есть родительский <object>.

+0

Спасибо. Будет ли это возвращать 'NodeList' длины ноль, если' 'не существует? Кроме того, не является '' родителем в этом случае и '' 'grandparent '? (Мой первый раз с XML, извините) – Svj0hn

+0

Выполнено, протестировано, подтверждено. Работает как рекламируется! – Svj0hn

0

Из кода ниже, мы можем получить все имена дочерних тегов документа и когда мы это входит в второй, если блок означает, что существует тег соединений, существующий как childnode для данного документа:
Как вы сказали, мы не знаем информации о родителях, мы можем использовать приведенную ниже строку в соответствии с присутствующим xml.
group.getChildNodes(). Пункт (0) .getChildNodes() ......

Document doc = dBuilder.parse(inputFile); 
doc.getDocumentElement().normalize(); 
NodeList groupList = doc.getChildNodes().item(0).getChildNodes(); 
for (int groupCount = 0; groupCount < groupList.getLength(); groupCount++) 
{ 
      Node group = groupList.item(groupCount); 
      if (group.getNodeType() == Node.ELEMENT_NODE) 
       { 
        if(group.getNodeName().equals("connections")) 
         { 
         } 
       } 
} 

Мой первый ответ в Stackoverflow.Hope это помогает.