代码之家  ›  专栏  ›  技术社区  ›  ant

xml子节点属性值

  •  3
  • ant  · 技术社区  · 15 年前

    我正在尝试读取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:

    • 我需要得到头衔的价值,身份证
    • tempi的属性值以及contento的madein属性值

    最好的方法是什么?

    编辑:

    @ Pascal Thivent

    也许创建方法和public string getvalue(string xml,element element name)一样是个好主意,如果该值不可用,那么在指定标记名的位置,该方法返回标记值或标记属性(可能将其名称作为附加方法参数提供)。

    如果标记值不可用,我真正想要的是获得特定的标记值或属性,因此我正在思考什么是最好的方法,因为我以前从未这样做过

    3 回复  |  直到 12 年前
        1
  •  4
  •   polygenelubricants    15 年前

    最好的解决方案是使用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>
    

    这是一个简短但可编译和运行的概念证明(与 FEX.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链接

        2
  •  2
  •   Paul Butcher    15 年前

    使用 Element.getAttribute 和element.setattribute

    在你的例子中, ((Node) content.item(0)).getFirstChild().getAttributes() . 假设 content 是个打字错误,你是说 contento ,GetFirstChild正确返回空,因为Contento没有子级。尝试: ((Node) contento.item(0)).getAttributes() 相反。

    另一个问题是使用 getFirstChild getChildNodes()[0] 在不检查返回值的情况下,您将面临获取子文本节点(而不是所需元素)的风险。

        3
  •  2
  •   Pascal Thivent    15 年前

    正如指出的那样, <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 相反?