为啥我在解析 XML 时会从此方法中得到重复记录?

Posted

技术标签:

【中文标题】为啥我在解析 XML 时会从此方法中得到重复记录?【英文标题】:Why am I getting duplicate records from this method when I parse XML?为什么我在解析 XML 时会从此方法中得到重复记录? 【发布时间】:2021-11-19 04:30:35 【问题描述】:

我正在尝试使用 Stax 解析 XML 中的内容。从它创建一个对象并将其放置在列表中。我为此创建了parseXml() 方法,但如果元素国家有两个以上的元素用户,它总是重复最后一个。

我用的方法是这个:

public static List<User> parseXML() 
    List<User> empList = new ArrayList<>();
    User emp = null;
    XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
    try 
        XMLEventReader xmlEventReader = xmlInputFactory.createXMLEventReader(new FileInputStream("C:\\Users\\HP\\Desktop\\untitled1\\src\\main\\xml\\users.xml"));
        while(xmlEventReader.hasNext())
            XMLEvent xmlEvent = xmlEventReader.nextEvent();
            if (xmlEvent.isStartElement())
                StartElement startElement = xmlEvent.asStartElement();
                if(startElement.getName().getLocalPart().equals("country"))
                    emp = new User();
                    //Get the 'id' attribute from Employee element
                    Attribute idAttr = startElement.getAttributeByName(new QName("name"));
                    if(idAttr != null)
                        emp.setCountry(idAttr.getValue());
                    
                
                //set the other varibles from xml elements
                else if(startElement.getName().getLocalPart().equals("first_name"))
                    xmlEvent = xmlEventReader.nextEvent();
                    emp.setFirst_name(xmlEvent.asCharacters().getData());
                else if(startElement.getName().getLocalPart().equals("last_name"))
                    xmlEvent = xmlEventReader.nextEvent();
                    emp.setLast_name(xmlEvent.asCharacters().getData());
                else if(startElement.getName().getLocalPart().equals("address"))
                    xmlEvent = xmlEventReader.nextEvent();
                    emp.setAddress(xmlEvent.asCharacters().getData());
                else if(startElement.getName().getLocalPart().equals("city"))
                    xmlEvent = xmlEventReader.nextEvent();
                    emp.setCity(xmlEvent.asCharacters().getData());
                else if(startElement.getName().getLocalPart().equals("email"))
                    xmlEvent = xmlEventReader.nextEvent();
                    emp.setEmail(xmlEvent.asCharacters().getData());
                
            
            //if Employee end element is reached, add employee object to list
            if(xmlEvent.isEndElement())
                EndElement endElement = xmlEvent.asEndElement();
                if(endElement.getName().getLocalPart().equals("user"))
                    empList.add(emp);
                
            
        
     catch (FileNotFoundException | XMLStreamException e) 
        e.printStackTrace();
    
    return empList;

这里是 XML:

<data>
    <continent name="Europe">
        <country name="United Kingdom">
            <!-- Users -->
            <user>
                <first_name>John</first_name>
                <last_name>Smith</last_name>
                <address>320 Regent Street</address>
                <city>London</city>
                <email>john.smith@gmail.com</email>
                <password>skek3E5k</password>
            </user>
            <user>
                <first_name>Michael</first_name>
                <last_name>Smith</last_name>
                <address>322 Regent Street</address>
                <city>London</city>
                <email>michael.smith@hotmail.com</email>
                <password>gk3288skW</password>
            </user>
        </country>
        <country name="Germany">
            <!-- Users -->
            <user>
                <first_name>Max</first_name>
                <last_name>Mustermann</last_name>
                <address>Berlinerstrasse 7</address>
                <city>Hamburg</city>
                <email>mmustermann@yahoo.com</email>
                <password>kdkei44229</password>
            </user>
          </country>
    </continent>
    <continent name="North America">
        <country name="United States">
            <!-- Users -->
            <user>
                <first_name>Julia</first_name>
                <last_name>Johnson</last_name>
                <address>300 Boylston Ave E</address>
                <city>Seattle</city>
                <email>julia.johnson@gmail.com</email>
                <password>49dksSSe3</password>
            </user>
        </country>
    </continent>
</data>

我的方法做错了什么?

【问题讨论】:

【参考方案1】:

只有在遇到&lt;country&gt; 时才创建User 的实例,但每个国家/地区可能有多个用户。您最终会为该国家/地区的每个用户添加相同的 User 对象。

我认为混淆可能来自这样一个事实,即您实际上是将emp 的引用添加到您的empList — 因此,当您为给定国家/地区的第二个、第三个等用户更改emp 时,您更改列表中已存在的同一 User 对象。

您可能应该在每次遇到&lt;user&gt; 标记时创建您的User 对象。但是,这将要求您还存储当前国家/地区。您的代码可能如下所示:

public static List<User> parseXML() 
        List<User> empList = new ArrayList<>();
        User emp = null;
        XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
        try 
            XMLEventReader xmlEventReader = xmlInputFactory.createXMLEventReader(new FileInputStream("C:\\Users\\HP\\Desktop\\untitled1\\src\\main\\xml\\users.xml"));
            String country = null;
            while(xmlEventReader.hasNext())
                XMLEvent xmlEvent = xmlEventReader.nextEvent();
                if (xmlEvent.isStartElement())
                    StartElement startElement = xmlEvent.asStartElement();
                    if(startElement.getName().getLocalPart().equals("country"))
                        //Get the 'id' attribute from Employee element
                        Attribute idAttr = startElement.getAttributeByName(new QName("name"));
                        if(idAttr != null)
                            country = idAttr.getValue();
                        
                    
                    else if (startElement.getName().getLocalPart().equals("user")) 
                        emp = new User();
                        emp.setCountry(country);
                    
                    //set the other varibles from xml elements
                    else if(startElement.getName().getLocalPart().equals("first_name"))
                        xmlEvent = xmlEventReader.nextEvent();
                        emp.setFirst_name(xmlEvent.asCharacters().getData());
                    else if(startElement.getName().getLocalPart().equals("last_name"))
                        xmlEvent = xmlEventReader.nextEvent();
                        emp.setLast_name(xmlEvent.asCharacters().getData());
                    else if(startElement.getName().getLocalPart().equals("address"))
                        xmlEvent = xmlEventReader.nextEvent();
                        emp.setAddress(xmlEvent.asCharacters().getData());
                    else if(startElement.getName().getLocalPart().equals("city"))
                        xmlEvent = xmlEventReader.nextEvent();
                        emp.setCity(xmlEvent.asCharacters().getData());
                    else if(startElement.getName().getLocalPart().equals("email"))
                        xmlEvent = xmlEventReader.nextEvent();
                        emp.setEmail(xmlEvent.asCharacters().getData());
                    
                
                //if Employee end element is reached, add employee object to list
                if(xmlEvent.isEndElement())
                    EndElement endElement = xmlEvent.asEndElement();
                    if(endElement.getName().getLocalPart().equals("user"))
                        empList.add(emp);
                    
                
            

         catch (FileNotFoundException | XMLStreamException e) 
            e.printStackTrace();
        
        return empList;
    

【讨论】:

以上是关于为啥我在解析 XML 时会从此方法中得到重复记录?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在使用 kotlin 将数据添加到 firebase 实时数据库时会得到重复值?

mybatis中查询时会将查询改成select count,这是为啥

为啥我在使用 pip install 命令时会收到此错误 [重复]

为啥我在使用 rand() 时会得到这种特殊的颜色模式?

为啥我在使用 useEffect 从区块链获取数据时会得到一系列 Promise?

为啥当我使用 BeautifulSoup 遍历我的文件时会得到相同的值?