【问题标题】:How to parse nested XML data and extract only the userid from it?如何解析嵌套的 XML 数据并仅从中提取用户 ID?
【发布时间】:2015-02-03 05:08:54
【问题描述】:

我有下面的xml布局,我想从中提取<key> </key>中的所有“userid”值并将它们加载到Java中的HashSet

<?xml version="1.0" encoding="UTF-8"?>
<response>
   <plds>
      <fld>consumerid</fld>
      <fld>last_set</fld>
   </plds>
   <record>
      <data>934463448   1417753752</data>
      <key_data>
         <key>
            <name>userid</name>
            <value>934463448</value>
         </key>
      </key_data>
   </record>
   <record>
      <data>1228059948  1417753799</data>
      <key_data>
         <key>
            <name>userid</name>
            <value>1228059948</value>
         </key>
      </key_data>
   </record>
</response>

我将从一个 url 获取以上 xml 数据,并且有可能我可以获得大的 XML 文件。解析上述 XML 并提取所有“userid”并将其加载到 Java 中的 HashSet 中的最佳方法是什么?

这就是我开始的 -

public static Set<String> getUserList(String host, String count) {

    Set<String> usrlist = new HashSet<String>();
    String url = "urlA"; // this url will return me above XML data
    InputStream is = new URL(url).openStream();
    BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));

    // not sure what I should do here which can
    // parse my above xml and extract all the
    // userid and load it into usrlist hash set

    return usrlist;
}

更新:-

这是我尝试过的 -

public static Set<String> getUserList() {

    Set<String> usrlist = new HashSet<String>();
    String url = "urlA"; // this url will return me above XML data
    InputStream is = new URL(url).openStream();
    BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document doc = builder.parse(new URL(url).openStream());

    XPathFactory xPathfactory = XPathFactory.newInstance();
    XPath xpath = xPathfactory.newXPath();
    XPathExpression expr = xpath.compile("//record/key_data/key[name='userid']/value");
    NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
    for (int i = 0; i < nodes.getLength(); i++) {
        usrlist.add(nodes.item(i).getNodeValue());
    }

    return usrlist;
}

但是我在usrlist 对象中没有得到任何用户ID?我在这里做错什么了吗?

【问题讨论】:

  • 为什么不使用杰克逊?
  • 像 JAXB 这样的东西可以提供帮助吗?但它与 xpath 在相同的环境中工作。整个文档将在内存中。
  • @alkis 您能否提供一个示例,我如何在这里使用 JAXB?我以前从未使用过 JAXB。
  • 当然。请检查我的答案。虽然我知道认为这是矫枉过正。
  • 以下任何答案有帮助吗?

标签: java xml parsing sax


【解决方案1】:

StAX 是解析大型 xmls 的有效方法

    XMLStreamReader r = XMLInputFactory.newInstance().createXMLStreamReader(is);
    while(r.hasNext()) {
        if (r.next() == XMLStreamReader.START_ELEMENT && r.getLocalName().equals("value")) {
            String value = r.getElementText();
            System.out.println(value);
        }
    }

【讨论】:

    【解决方案2】:

    如果上面的文档比较小,可以load the entire document,然后应用下面的xpath来提取文档中的key:

    //record/key_data/key[name='userid']/value
    

    编辑

    我认为你有一个错误 - 使用getTextContent() 获取text(),而不是getNodeValue()

    for (int i = 0; i < nodes.getLength(); i++) {
        usrlist.add( nodes.item(i).getTextContent());
    }
    

    调试代码:

    Set<String> usrlist = new HashSet<String>();
    String myXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
            "<response>\n" +
            ...
            "</response>";
    InputStream is = new ByteArrayInputStream( myXml.getBytes( ) );
    BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
    
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document doc = builder.parse(new InputSource(rd));
    
    XPathFactory xPathfactory = XPathFactory.newInstance();
    XPath xpath = xPathfactory.newXPath();
    XPathExpression expr = xpath.compile("//record/key_data/key[name='userid']/value");
    NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
    for (int i = 0; i < nodes.getLength(); i++) {
        usrlist.add( nodes.item(i).getTextContent());
    }
    
    return usrlist;
    

    【讨论】:

    • 感谢您的建议。它可能很小,也可能不大。有时它会很小,有时它不会很小。
    • 这是获取用户标识的正确表达式吗?不知何故,当我使用它时,我得到了空值。
    • 是的,我很确定 - 推送transform button here。我猜我们有一些命名空间要处理 - 你能仔细检查输入的 Xml 是否与你所拥有的完全一致?
    • 我已经用我正在尝试的代码更新了这个问题。看看我是不是做错了什么?
    • 该值为null的原因是因为需要使用getTextContent来获取元素的text(),而不是getNodeValue() - 我已经更新了。
    【解决方案3】:

    我现在认为 JAXB 有点矫枉过正,其他两个答案要好得多,但是既然您要求提供有关 JAXB 的示例,我很乐意提供帮助。

    您必须创建下面的类,这样才能将 XML 映射到 Java 对象。

    Response.java

    import java.util.List;
    
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement
    public class Response {
    
        List<Plds> pldslist;
        List<Record> recordlist;
    
        @XmlElement(name = "plds")
        public void setPlds(List<Plds> pldslist) {
            this.pldslist = pldslist;
        }
    
        public List<Plds> getPlds() {
            return pldslist;
        }
    
        @XmlElement(name = "record")
        public void setRecord(List<Record> recordlist) {
            this.recordlist = recordlist;
        }
    
        public List<Record> getRecord() {
            return recordlist;
        }
    
    }
    

    Record.java

    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement
    public class Record {
    
        String data;
        KeyData keyData;
    
        public String getData() {
            return data;
        }
    
        @XmlElement(name = "data")
        public void setData(String data) {
            this.data = data;
        }
    
        public KeyData getKeyData() {
            return keyData;
        }
    
        @XmlElement(name = "key_data")
        public void setKeyData(KeyData keyData) {
            this.keyData = keyData;
        }
    
    }
    

    Plds.java

    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement
    public class Plds {
    
        private String fld;
    
        public String getFld() {
            return fld;
        }
    
        @XmlElement(name = "fld")
        public void setFld(String fld) {
            this.fld = fld;
        }
    
    }
    

    KeyData.java

    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement
    public class KeyData {
    
        Key key;
    
        public Key getKey() {
            return key;
        }
    
        @XmlElement(name = "key")
        public void setKey(Key key) {
            this.key = key;
        }
    }
    

    Key.java

    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement
    public class Key {
    
        String name;
        String value;
    
        public String getName() {
            return name;
        }
    
        @XmlElement(name = "name")
        public void setname(String name) {
            this.name = name;
        }
    
        public String getValue() {
            return value;
        }
    
        @XmlElement(name = "value")
        public void setKey(String value) {
            this.value = value;
        }
    }
    

    Main.java 示例

    import java.io.File;
    
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.Unmarshaller;
    
    
    public class Main {
    
        public static void main(String[] args) 
        throws Exception
        {
            File file = new File("PATH_HERE/file.xml");
            JAXBContext jaxbContext = JAXBContext.newInstance(Response.class);
    
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            Response response = (Response) jaxbUnmarshaller.unmarshal(file);
            for(Record rec : response.getRecord())
                System.out.println("Name : " + rec.getKeyData().getKey().getName() + " | " + "Value : " + rec.getKeyData().getKey().getValue());
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-16
      • 2014-04-09
      • 2023-01-23
      • 2013-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多