private void parseResponseByXmlPath()

in hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/http/HttpCollectImpl.java [346:424]


    private void parseResponseByXmlPath(String resp, Metrics metrics,
                                        CollectRep.MetricsData.Builder builder, Long responseTime) {
        HttpProtocol http = metrics.getHttp();
        List<String> aliasFields = metrics.getAliasFields();
        String xpathExpression = http.getParseScript();
        if (!StringUtils.hasText(xpathExpression)) {
            log.warn("Http collect parse type is xmlPath, but the xpath expression is empty.");
            builder.setCode(CollectRep.Code.FAIL);
            builder.setMsg("XPath expression is empty");
            return;
        }
        int keywordNum = CollectUtil.countMatchKeyword(resp, http.getKeyword());

        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
            dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
            dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
            dbf.setXIncludeAware(false);
            dbf.setExpandEntityReferences(false);

            DocumentBuilder db = dbf.newDocumentBuilder();
            Document document = db.parse(new InputSource(new StringReader(resp)));

            XPathFactory xpathFactory = XPathFactory.newInstance();
            XPath xpath = xpathFactory.newXPath();

            NodeList nodeList = (NodeList) xpath.evaluate(xpathExpression, document, XPathConstants.NODESET);

            if (nodeList == null || nodeList.getLength() == 0) {
                log.debug("XPath expression '{}' returned no nodes.", xpathExpression);
                boolean requestedSummaryFields = aliasFields.stream()
                        .anyMatch(alias -> NetworkConstants.RESPONSE_TIME.equalsIgnoreCase(alias)
                                || CollectorConstants.KEYWORD.equalsIgnoreCase(alias));

                if (requestedSummaryFields) {
                    CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
                    for (String alias : aliasFields) {
                        if (NetworkConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
                            valueRowBuilder.addColumn(responseTime.toString());
                        } else if (CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) {
                            valueRowBuilder.addColumn(Integer.toString(keywordNum));
                        } else {
                            valueRowBuilder.addColumn(CommonConstants.NULL_VALUE);
                        }
                    }
                    builder.addValueRow(valueRowBuilder.build());
                }
                return;
            }

            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();

                for (String alias : aliasFields) {
                    if (NetworkConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
                        valueRowBuilder.addColumn(responseTime.toString());
                    } else if (CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) {
                        valueRowBuilder.addColumn(Integer.toString(keywordNum));
                    } else {
                        try {
                            String value = (String) xpath.evaluate(alias, node, XPathConstants.STRING);
                            valueRowBuilder.addColumn(StringUtils.hasText(value) ? value : CommonConstants.NULL_VALUE);
                        } catch (XPathExpressionException e) {
                            log.warn("Failed to evaluate XPath '{}' for node [{}]: {}", alias, node.getNodeName(), e.getMessage());
                            valueRowBuilder.addColumn(CommonConstants.NULL_VALUE);
                        }
                    }
                }
                builder.addValueRow(valueRowBuilder.build());
            }

        } catch (Exception e) {
            log.warn("Failed to parse XML response with XPath '{}': {}", xpathExpression, e.getMessage(), e);
            builder.setCode(CollectRep.Code.FAIL);
            builder.setMsg("Failed to parse XML response: " + e.getMessage());
        }
    }