Я звоню в службу OData (по аналогии с вызовом API REST), используя мою Java-программу, и получаю ответ также в формате XML. В ответ я получаю XML, в котором мне нужно только прочитать определенные свойства / атрибуты XML, поэтому я использую XPath для этого. Однако проблема в том, что я могу читать только 1 набор (или 1-й набор) атрибутов XML, но не другие. Что я понимаю в XPath, так это то, что мне нужно дать имя родительского атрибута, чтобы синтаксический анализ начался с этого уровня до дочерних атрибутов, но кое-как он не работает должным образом.
Ниже приведен ответ XML, и здесь есть каждый тег <entry>
, а внутри каждого тега <entry>
я хочу прочитать только дочерние атрибуты / узлы, которые входят в <m:properties>
, например:
<m:properties>
<d:Role_MappingId>3503</d:Role_MappingId>
<d:Org_RelationshipId>1</d:Org_RelationshipId>
<d:Role_Id>1</d:Role_Id>
<d:Role_Mapping_Active>true</d:Role_Mapping_Active>
<d:RoleName>test</d:RoleName>
<d:Role_Description>
dummy description,
</d:Role_Description>
<d:RoleGroup>dummy group</d:RoleGroup>
</m:properties>
Полный XML-ответ для вашей справки:
<link href="Relationships(1)/RoleToRelationshipMappings" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/RoleToRelationshipMappings" title="RoleToRelationshipMappings" type="application/atom+xml;type=feed">
<m:inline>
<feed xml:base="http://localhost:8080/com.test/PortalOData.svc/">
<id>...</id>
<title type="text">RoleToRelationshipMappings</title>
<updated>2019-04-03T15:24:15.429+05:30</updated>
<author>...</author>
<link href="Relationships(1)/RoleToRelationshipMappings" rel="self" title="RoleToRelationshipMappings"/>
<entry>
<id>
http://localhost:8080/com.test/PortalOData.svc/RoleToRelationshipMappings(3503)
</id>
<title type="text">RoleToRelationshipMappings</title>
<updated>2019-04-03T15:24:15.429+05:30</updated>
<category term="cmo.test.portal.servicelayer.odataentities.RoleToRelationshipMapping" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
<link href="RoleToRelationshipMappings(3503)" rel="edit" title="RoleToRelationshipMapping"/>
<content type="application/xml">
<m:properties>
<d:Role_MappingId>3503</d:Role_MappingId>
<d:Org_RelationshipId>1</d:Org_RelationshipId>
<d:Role_Id>1</d:Role_Id>
<d:Role_Mapping_Active>true</d:Role_Mapping_Active>
<d:RoleName>SNR</d:RoleName>
<d:Role_Description>
This entity can make a serial number request from a MAH,
</d:Role_Description>
<d:RoleGroup>SNR_REQUEST_TYPE</d:RoleGroup>
</m:properties>
</content>
</entry>
<entry>...</entry>
<entry>...</entry>
<entry>...</entry>
<entry>...</entry>
<entry>...</entry>
<entry>...</entry>
<entry>...</entry>
<entry>...</entry>
</feed>
</m:inline>
</link>
Если вы заметили в приведенном выше XML, родительский узел - <feed>
, и внутри него есть повторные <entry>
узлы и для каждого <entry>
узла есть некоторые дочерние атрибуты, но Я хочу прочитать только те атрибуты, которые подпадают под <m:properties>
, например <d:Role_MappingId>
или <d:Org_RelationshipId>
и для каждого <entry>
.
Проблема в том, что я могу читать, но только для 1 <entry>
, но не для других <entry>
.
Пожалуйста, помогите исправить или сообщить основную причину этого.
Это моя программа на Java:
public Map<String, MetricModel> readResponse(BufferedReader bufferedReader) throws Exception {
Map<String, MetricModel> map = null;
List <String> roles = null;
String line = "";
StringBuffer response = new StringBuffer();
while ((line = bufferedReader.readLine()) != null) {
response.append(line);
}
String xml = response.toString();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(new ByteArrayInputStream(xml.getBytes()));
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
try {
if (xml.contains("entry") == false) {
throw new Exception();
} else {
roles = new ArrayList<>();
String expression = "/entry";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
Node nNode = nodeList.item(i);
logger.info("\nCurrent Element :" + nNode.getNodeName());
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
logger.info(
"Role_Mapping_Id : " + eElement.getElementsByTagName("d:Role_MappingId").item(0).getTextContent());
logger.info("Org_Relationship_Id : " + eElement.getElementsByTagName("d:Org_RelationshipId")
.item(0)
.getTextContent());
logger.info("Role_Id : " + eElement.getElementsByTagName("d:Role_Id").item(0).getTextContent());
roles.add(eElement.getElementsByTagName("d:Role_Id").item(0).getTextContent()); //Adding roles to list
logger.info("Role_Mapping_Active : " + eElement.getElementsByTagName("d:Role_Mapping_Active")
.item(0)
.getTextContent());
logger.info("RoleName : " + eElement.getElementsByTagName("d:RoleName").item(0).getTextContent());
logger.info(
"Role_Description : " + eElement.getElementsByTagName("d:Role_Description").item(0).getTextContent());
logger.info("RoleGroup : " + eElement.getElementsByTagName("d:RoleGroup").item(0).getTextContent());
}
}
}
map = prepareDataForMetricModel(roles);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XPathExpressionException e) {
e.printStackTrace();
}finally{
logger.info("finally block");
return map;
}
Здесь, в программе, я использовал выражение вроде
String expression = "/entry";
Я изменил это на следующее, но все еще не могу прочитать для всех записей.
String expression = "/feed/entry";