JAVA元素.getElementsByTagName限制为顶层

21

我有一个如下的XML文件:

<rootNode>
    <link>http://rootlink/</link>
    <image>
        <link>http://imagelink/</link>
        <title>This is the title</title>
    </image>
</rootNode>

使用DOM的XML Java代码如下:

NodeList rootNodeList = element.getElementsByTagName("link");

这将给我所有的“link”元素,包括顶层和“image”节点内部的元素。

有没有一种方法只获取根节点(rootNode)中一个层级而不是两个层级的“link”标签,就像图像链接一样?换句话说,我只想要http://rootlink/这个链接。

5个回答

13
你可以使用XPath:

您可以使用XPath

XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();
NodeList links = (NodeList) xpath.evaluate("rootNode/link", element,
    XPathConstants.NODESET);

11

我也找不到任何可以做到这点的方法,所以我写了这个辅助函数:

 public static List<Element> getChildrenByTagName(Element parent, String name) {
    List<Element> nodeList = new ArrayList<Element>();
    for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
      if (child.getNodeType() == Node.ELEMENT_NODE && 
          name.equals(child.getNodeName())) {
        nodeList.add((Element) child);
      }
    }

    return nodeList;
  }

if循环始终为真。我尝试了这样的方式...for (int nodeCnt = 0; nodeCnt < nl.getLength(); nodeCnt++) { if (nl.item(nodeCnt).getNodeType() == Node.ELEMENT_NODE && tagName.equals(nl.item(nodeCnt).getNodeName())) { } }这里的nl是包含所有元素(包括子元素)的节点列表。 - Gopi
1
我来到这里是为了寻找用Javascript实现这个功能的方法。这个答案对我很有帮助。我从这段代码开始,将其转换成了JS。function getChildrenByTagName(parent, name) { var nodeList = []; for (var child = parent.firstChild; child != null; child = child.nextSibling) { if (child.nodeType == 1 && name == child.nodeName) { nodeList.push(child); } } return nodeList; } - curioustechizen
PHP:function getChildrenByTagName($parent, $name){ $nodeList = array(); foreach($parent->getElementsByTagName($name) as $child){ if($child->nodeType == 1){ array_push($nodeList, $child); } } return $nodeList; } - thethakuri

3

如果您可以使用JDOM,则可以这样做:

element.getChildren("link");

使用标准Dom,你只能迭代子节点列表(通过调用getChildNodes()并检查NodeList中的每个项(i),挑选出与匹配名称相符的节点。


我考虑过使用JDOM,但是我已经用DOM写了很多代码。我必须评估转换的工作量。但是难道没有使用DOM的方法吗? - user152090
我认为没有方便的方法来实现它,但是你可以创建一个方法,调用getChildNodes()方法并检查每个项目的名称,将这些项目添加到新的NodeList中,然后返回该NodeList。在需要获取指定子项的位置使用该方法。或者你可以选择使用JDom,我发现它更容易处理。 - Rich Seller
谢谢。我会研究不同的解决方案建议。感谢您的快速回复。 - user152090

1

我知道这是一个老问题,但我有一个另外的解决方案要添加。

虽然不是最高效的,但它能够工作:

使用getElementsByTagName获取所有的子元素,然后检查每个子元素是否具有与你开始的那个父元素相同的父元素。

我使用这种方法是因为我有一组结果,每个结果可能会嵌套在其中。当我调用我的Result构造函数时,我需要添加任何嵌套的结果,但是由于它们自己会寻找它们自己的子元素,我不想将子元素添加到当前级别(它们的父级将会添加它们)。

例如:

NodeList children = resultNode.getElementsByTagName("result");
for(int i = 0; i<children.getLength(); i++){
   // make sure not to pick up grandchildren.
   if(children.item(i).getParentNode().isSameNode(resultNode)){
        addChildResult(new Result((Element)children.item(i)));
    }
}

希望这有所帮助。

0
我写了这个函数来通过标签名获取节点值,限制在顶层。
public static String getValue(Element item, String tagToGet, String parentTagName) {
    NodeList n = item.getElementsByTagName(tagToGet);
    Node nodeToGet = null;
    for (int i = 0; i<n.getLength(); i++) {
        if (n.item(i).getParentNode().getNodeName().equalsIgnoreCase(parentTagName)) {
            nodeToGet = n.item(i);
        }
    }
    return getElementValue(nodeToGet);
}

public final static String getElementValue(Node elem) {
    Node child;
    if (elem != null) {
        if (elem.hasChildNodes()) {
            for (child = elem.getFirstChild(); child != null; child = child
                    .getNextSibling()) {
                if (child.getNodeType() == Node.TEXT_NODE) {
                    return child.getNodeValue();
                }
            }
        }
    }
    return "";
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接