java XML子节点属性值

np8igboo  于 2023-03-28  发布在  Java
关注(0)|答案(3)|浏览(122)

我正在尝试读取XML文件,例如:

<entry>
    <title>FEED TITLE</title>
    <id>5467sdad98787ad3149878sasda</id>
    <tempi type="application/xml">
      <conento xmlns="http://mydomainname.com/xsd/radiofeed.xsd" madeIn="USA" />
    </tempi>
</entry>

下面是我目前拥有的代码:http://pastebin.com/huKP4KED
下面是我需要的,关于上面的XML:

  • 我需要得到标题的值,id
  • tempi的属性值以及contento的madeIn属性值

做这件事的最好方法是什么?

编辑

@Pascal Thivent
也许创建方法是个好主意,比如public String getValue(String xml,Element elementname),在这里指定标记名称,如果值不可用,则方法返回标记值或标记属性(可能给予名称作为附加方法参数
如果标签值不可用,我真的想获得某些标签值或属性,所以我正在思考什么是最好的方法,因为我以前从未这样做过。

lbsnaicq

lbsnaicq1#

最好的解决方案是使用XPath。假设我们有以下feed.xml文件:

<?xml version="1.0" encoding="UTF-8" ?>
<entries>
<entry>
    <title>FEED TITLE 1</title>
    <id>id1</id>
    <tempi type="type1">
      <conento xmlns="dontcare?" madeIn="MadeIn1" />
    </tempi>
</entry>
<entry>
    <title>FEED TITLE 2</title>
    <id>id2</id>
    <tempi type="type2">
      <conento xmlns="dontcare?" madeIn="MadeIn2" />
    </tempi>
</entry>
<entry>
    <id>id3</id>
</entry>
</entries>

下面是一个简短但可编译和运行的概念证明(feed.xml文件位于同一目录中)。

import javax.xml.xpath.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
import java.util.*;

public class XPathTest {
    static class Entry {
        final String title, id, origin, type;
        Entry(String title, String id, String origin, String type) {
            this.title = title;
            this.id = id;
            this.origin = origin;
            this.type = type;
        }
        @Override public String toString() {
            return String.format("%s:%s(%s)[%s]", id, title, origin, type);
        }
    }

    final static XPath xpath = XPathFactory.newInstance().newXPath();
    static String evalString(Node context, String path) throws XPathExpressionException {
        return (String) xpath.evaluate(path, context, XPathConstants.STRING);
    }

    public static void main(String[] args) throws Exception {
        File file = new File("feed.xml");
        Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file);
        NodeList entriesNodeList = (NodeList) xpath.evaluate("//entry", document, XPathConstants.NODESET);

        List<Entry> entries = new ArrayList<Entry>();
        for (int i = 0; i < entriesNodeList.getLength(); i++) {
            Node entryNode = entriesNodeList.item(i);
            entries.add(new Entry(
                evalString(entryNode, "title"),
                evalString(entryNode, "id"),
                evalString(entryNode, "tempi/conento/@madeIn"),
                evalString(entryNode, "tempi/@type")
            ));
        }
        for (Entry entry : entries) {
            System.out.println(entry);
        }
    }
}

这将生成以下输出:

id1:FEED TITLE 1(MadeIn1)[type1]
id2:FEED TITLE 2(MadeIn2)[type2]
id3:()[]

请注意,使用XPath可以使值检索变得非常简单、直观、易读和直接,而且还可以很好地处理“丢失”的值。

API链接

yhuiod9q

yhuiod9q2#

使用Element.getAttribute和Element.setAttribute
在您的示例中,((Node) content.item(0)).getFirstChild().getAttributes()。假设content是一个输入错误,您指的是contento,getFirstChild将正确返回NULL,因为contento没有子级。请尝试:((Node) contento.item(0)).getAttributes()代替。
另一个问题是,如果使用getFirstChildgetChildNodes()[0]而不检查返回值,您可能会选择子文本节点,而不是您想要的元素。

a2mppw5e

a2mppw5e3#

如前所述,<contento>没有任何子元素,因此:

(contento.item(0)).getFirstChild().getAttributes()

你应该把节点当作元素,并使用getAttribute(String),类似这样:

((Element)contento.item(0)).getAttribute("madeIn")

下面是你的代码的修改版本(它不是我写过的最健壮的代码):

InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(inputStream);
doc.getDocumentElement().normalize();
System.out.println("Root element " + doc.getDocumentElement().getNodeName());
NodeList nodeLst = doc.getElementsByTagName("entry");
System.out.println("Information of all entries");

for (int s = 0; s < nodeLst.getLength(); s++) {

    Node fstNode = nodeLst.item(s);

    if (fstNode.getNodeType() == Node.ELEMENT_NODE) {

        Element fstElmnt = (Element) fstNode;

        NodeList title = fstElmnt.getElementsByTagName("title").item(0).getChildNodes();
        System.out.println("Title : " + (title.item(0)).getNodeValue());

        NodeList id = fstElmnt.getElementsByTagName("id").item(0).getChildNodes();
        System.out.println("Id: " + (id.item(0)).getNodeValue());

        Node tempiNode = fstElmnt.getElementsByTagName("tempi").item(0);
        System.out.println("Type : " + ((Element) tempiNode).getAttribute("type"));

        Node contento = tempiNode.getChildNodes().item(0);
        System.out.println("Made in : " + ((Element) contento).getAttribute("madeIn"));
    }
}

在XML代码段上运行它会产生以下输出:

Root element entry
Information of all entries
Title : FEED TITLE
Id: 5467sdad98787ad3149878sasda
Type : application/xml
Made in : USA

顺便问一下,你有没有考虑过用Rome之类的东西来代替?

相关问题