Java org.w3c.dom-递归查找并返回节点列表中的属性值

Java org.w3c.dom-递归查找并返回节点列表中的属性值,java,dom,recursion,Java,Dom,Recursion,我目前正在解析来自web服务的XML响应。它返回有限数量的元素。我目前正在迭代此类结果的NodeList 当我迭代这个过程时,有时我需要找到每个元素中存在的属性的值。在这种情况下,我想调用一个方法,该方法遍历所有子节点(可能还有子节点的子节点等),并返回属性值 我已尝试递归地执行此操作: private String findAttrInChildren(Element element, String tag) { if (!element.getAttribute(tag).isEmp

我目前正在解析来自web服务的XML响应。它返回有限数量的
元素。我目前正在迭代此类结果的
NodeList

当我迭代这个过程时,有时我需要找到每个
元素中存在的属性的值。在这种情况下,我想调用一个方法,该方法遍历所有子节点(可能还有子节点的子节点等),并返回属性值

我已尝试递归地执行此操作:

private String findAttrInChildren(Element element, String tag) {
    if (!element.getAttribute(tag).isEmpty()) {
        return element.getAttribute(tag);
    }

    NodeList children = element.getChildNodes();
    for (int i = 0, len = children.getLength(); i < len; i++) {
        if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
            Element childElement = (Element) children.item(i);
            return findAttrInChildren(childElement, tag);
        }
    }

    // We didn't find it, return null
    return null;
}
私有字符串findAttrInChildren(元素、字符串标记){
如果(!element.getAttribute(tag.isEmpty()){
返回元素.getAttribute(标记);
}
NodeList childrends=element.getChildNodes();
for(int i=0,len=children.getLength();i

不幸的是,这不起作用。递归是这里最好的方法吗?我认为,我想在最后返回一个值,这一事实在某种程度上把我搞砸了,而不是实现一个
void
递归方法。

你离开递归太早了。给定

if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
    Element childElement = (Element) children.item(i);
    return findAttrInChildren(childElement, tag);
}
这将在第一个子元素处结束递归搜索-无论该子元素或其子元素是否具有该属性

因此,如果返回的属性不为null,则进行测试:

if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
    Element childElement = (Element) children.item(i);
    String attr = findAttrInChildren(childElement, tag);
    if (attr != null)
        return attr;
}

您过早地离开递归。给定

if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
    Element childElement = (Element) children.item(i);
    return findAttrInChildren(childElement, tag);
}
这将在第一个子元素处结束递归搜索-无论该子元素或其子元素是否具有该属性

因此,如果返回的属性不为null,则进行测试:

if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
    Element childElement = (Element) children.item(i);
    String attr = findAttrInChildren(childElement, tag);
    if (attr != null)
        return attr;
}

我知道你的问题已经得到了回答,你得到了一个有效的答案,但是你可以让你的代码变得更好。您应该避免使用2个出口点,而是使用1个出口点,并且始终避免使用null。为了满足这两个需求,我将修改您的代码,并为您提供一个新的代码。我希望你能理解这些变化。我使用Optional来避免null,并使您的代码更具可读性和可理解性

private static Optional<String> findAttributeInChildren(Element element, String tag) {
        Optional<String> attr = Optional.empty();
        if (!element.getAttribute(tag).isEmpty()) {
            attr = Optional.of(element.getAttribute(tag));

        } else {
            NodeList children = element.getChildNodes();
            int len = children.getLength();
            for (int i = 0; (i < len) && (!attr.isPresent()); i++) {
                if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
                    Element childElement = (Element) children.item(i);
                    attr = findAttributeInChildren(childElement, tag);
                }
            }
        }

        return attr;
    }
而不是

findAttributeInChildren(x,y) == null

我知道你的问题已经得到了回答,你得到了一个有效的答案,但是你可以让你的代码变得更好。您应该避免使用2个出口点,而是使用1个出口点,并且始终避免使用null。为了满足这两个需求,我将修改您的代码,并为您提供一个新的代码。我希望你能理解这些变化。我使用Optional来避免null,并使您的代码更具可读性和可理解性

private static Optional<String> findAttributeInChildren(Element element, String tag) {
        Optional<String> attr = Optional.empty();
        if (!element.getAttribute(tag).isEmpty()) {
            attr = Optional.of(element.getAttribute(tag));

        } else {
            NodeList children = element.getChildNodes();
            int len = children.getLength();
            for (int i = 0; (i < len) && (!attr.isPresent()); i++) {
                if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
                    Element childElement = (Element) children.item(i);
                    attr = findAttributeInChildren(childElement, tag);
                }
            }
        }

        return attr;
    }
而不是

findAttributeInChildren(x,y) == null