Невозможно проанализировать данные XML в объект Java с помощью XPath - PullRequest
2 голосов
/ 05 апреля 2019

Я звоню в службу 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";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...