XML child node attribute value

前端 未结 3 894
孤独总比滥情好
孤独总比滥情好 2020-12-16 08:05

I\'m trying to read xml file, ex :


    FEED TITLE
    5467sdad98787ad3149878sasda
    

        
相关标签:
3条回答
  • 2020-12-16 08:26

    As pointed out, <contento> doesn't have any child so instead of:

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

    You should treat the Node as Element and use getAttribute(String), something like this:

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

    Here is a modified version of your code (it's not the most robust code I've written):

    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"));
        }
    }
    

    Running it on your XML snippet produces the following output:

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

    By the way, did you consider using something like Rome instead?

    0 讨论(0)
  • 2020-12-16 08:32

    The best solution for this is to use XPath. Your pastebin is expired, but here's what I gathered. Let's say we have the following feed.xml file:

    <?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>
    

    Here's a short but compile-and-runnable proof-of-concept (with feed.xml file in the same directory).

    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);
            }
        }
    }
    

    This produces the following output:

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

    Note how using XPath makes the value retrieval very simple, intuitive, readable, and straightforward, and "missing" values are also gracefully handled.

    API links

    • package javax.xml.xpath
    • http://www.w3.org/TR/xpath
    • Wikipedia/XPath
    0 讨论(0)
  • 2020-12-16 08:36

    Use Element.getAttribute and Element.setAttribute

    In your example, ((Node) content.item(0)).getFirstChild().getAttributes(). Assuming that content is a typo, and you mean contento, getFirstChild is correctly returning NULL as contento has no children. Try: ((Node) contento.item(0)).getAttributes() instead.

    Another issue is that by using getFirstChild and getChildNodes()[0] without checking the return value, you are running the risk of picking up child text nodes, instead of the element you want.

    0 讨论(0)
提交回复
热议问题