为什么在运行 StAX Parser 时出现 NullPointerException?

Why I get NullPointerException when running StAX Parser?(为什么在运行 StAX Parser 时出现 NullPointerException?)
本文介绍了为什么在运行 StAX Parser 时出现 NullPointerException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我正在尝试用 Java 编写 StAX XML 解析器,但总是出现 NullPointerException 错误.请帮我解决这个问题.完整问题:

<块引用>

线程main"中的异常;java.lang.NullPointerException 在org.example.shoesshop.parser.STAXParser.parseXMLfile(STAXParser.java:68)在 org.example.shoesshop.parser.STAXParser.main(STAXParser.java:101)

这是 StAX Parser 的一个类:

公共类 STAXParser 扩展 DefaultHandler {私有静态列表<鞋子>parseXMLfile(字符串文件名){列出<鞋子>shoesList = new ArrayList<>();鞋鞋 = null;XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();尝试 {XMLEventReader reader = xmlInputFactory.createXMLEventReader(new FileInputStream(fileName));while (reader.hasNext()){XMLEvent xmlEvent = reader.nextEvent();如果(xmlEvent.isStartElement()){StartElement startElement = xmlEvent.asStartElement();if(startElement.getName().getLocalPart().equals(鞋")){鞋=新鞋();属性 idAttr = startElement.getAttributeByName(new QName("id"));如果(idAttr!= null){shoes.setId(Integer.parseInt(idAttr.getValue()));}} else if (startElement.getName().getLocalPart().equals("title")){xmlEvent = reader.nextEvent();shoes.setTitle(xmlEvent.asCharacters().getData());//错误第 68 行} else if (startElement.getName().getLocalPart().equals("brand")){xmlEvent = reader.nextEvent();shoes.setBrand(Brand.fromValue(xmlEvent.asCharacters().getData()));} else if (startElement.getName().getLocalPart().equals("category")){xmlEvent = reader.nextEvent();shoes.setCategory(Category.fromValue(xmlEvent.asCharacters().getData()));} else if (startElement.getName().getLocalPart().equals(season")){xmlEvent = reader.nextEvent();shoes.setSeason(Season.fromValue(xmlEvent.asCharacters().getData()));} else if (startElement.getName().getLocalPart().equals("price")){xmlEvent = reader.nextEvent();shoes.setPrice(Double.parseDouble(xmlEvent.asCharacters().getData()));}}如果(xmlEvent.isEndElement()){EndElement endElement = xmlEvent.asEndElement();if(endElement.getName().getLocalPart().equals(鞋")){shoesList.add(鞋子);}}}} 捕捉(FileNotFoundException | XMLStreamException exc){exc.printStackTrace();} 返回鞋子列表;}公共静态 void main(String[] args) 抛出异常 {System.out.println(STAX 解析器");System.out.println();System.out.println("结果:
");System.out.println();字符串文件名 = ShoesShop.xml";列出<鞋子>shoesList = parseXMLfile(fileName);//错误第101行对于(鞋鞋:shoesList){System.out.println(shoes.toString());}}}

这是一个 XML 文件

还有一个用于鞋子的 Java 类

@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "鞋子", propOrder = {标题",品牌",类别",季节",性别",详情",价格"})公共课鞋扩展实体{@XmlElement(必需 = 真)受保护的字符串标题;@XmlElement(必需 = 真)@XmlSchemaType(name = "字符串")受保护的品牌品牌;@XmlElement(必需 = 真)@XmlSchemaType(name = "字符串")受保护的类别类别;@XmlElement(必需 = 真)@XmlSchemaType(name = "字符串")受保护的季节;@XmlElement(必需 = 真)受保护的鞋子.性别性别;@XmlElement(必需 = 真)受保护的鞋子.详细信息;受保护的双倍价格;@XmlAttribute(name = "stock", required = true)受保护的布尔库存;@XmlAttribute(name = "最想要的")受保护的布尔最想要的;公共字符串 getTitle() {返回标题;}公共无效 setTitle(字符串值){this.title = 值;}公共品牌 getBrand(){回归品牌;}public void setBrand(品牌价值){this.brand = 价值;}公共类别 getCategory(){返回类别;}公共无效 setCategory(类别值){this.category = 值;}公共季节 getSeason(){回归季节;}公共无效setSeason(季节值){this.season = 价值;}public Shoes.Gender getGender() {返回性别;}公共无效 setGender(Shoes.Gender 值){this.gender = 价值;}公共鞋.详细信息 getDetails() {退货详情;}public void setDetails(Shoes.Details 值) {this.details = 价值;}公共双getPrice(){退货价格;}公共无效 setPrice(双值){this.price = 价值;}公共布尔 isStock() {退货;}公共无效 setStock(布尔值){this.stock = 价值;}公共布尔 isMostWanted() {返回最想要的;}公共无效 setMostWanted(布尔值){this.most Wanted = 价值;}@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "", propOrder = {})公共静态类详细信息{@XmlElement(必需 = 真)受保护的字符串亮点;@XmlElement(必需 = 真)受保护的字符串组合;公共字符串 getHighlights() {返回亮点;}公共无效setHighlights(字符串值){this.highlights = 价值;}公共字符串 getComposition() {返回组成;}公共无效setComposition(字符串值){this.composition = 价值;}}@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "", propOrder = {u043cu0443u0436u0441u043au043eu0439或u0416u0435u043du0441u043au0438u0439"})公共静态类性别{@XmlElementRefs({@XmlElementRef(name = "u0436u0435u043du0441u043au0438u0439", 命名空间 = "http://www.example.org/ShoesShop", type = JAXBElement.class, required = false),@XmlElementRef(name = "u043cu0443u0436u0441u043au043eu0439", 命名空间 = "http://www.example.org/ShoesShop", type = JAXBElement.class, required = false)})受保护的列表<JAXBElement<字符串>>男性或女性;公共列表<JAXBElement<字符串>>getMaleOrFemale() {if (maleOrFemale == null) {maleOrFemale = new ArrayList<JAXBElement<String>>();}返回 this.maleOrFemale;}}@覆盖公共字符串 toString(){StringBuilder builder = new StringBuilder();builder.append("[title=");builder.append(title);builder.append(", 品牌=");builder.append(品牌);builder.append(", category=");builder.append(类别);builder.append(", season=");builder.append(季节);builder.append(", price=");builder.append(价格);builder.append("]");返回 builder.toString();}}

我还需要知道如何将接收到的数据写入新的 XML 文件.

解决方案

已更新: 对原始答案的评论:

<块引用>

它不起作用,它给出了同样的错误

这意味着问题是因为 shoes 变量是 null,这在 debugger 中很容易看到.使用调试器会为我们节省很多时间,所以请开始使用调试器.

为了使 shoesnull,看来代码遇到了一个不是鞋子元素.

要修复代码,添加一个空检查,并在处理 Shoes 元素结束时设置 shoes = null:

} else if (startElement.getName().getLocalPart().equals("title")) {if (shoes != null) {//<===== 添加这个shoes.setTitle(reader.getElementText());//<===== 解决这个问题(见原始答案)}

if (xmlEvent.isEndElement()) {EndElement endElement = xmlEvent.asEndElement();if (endElement.getName().getLocalPart().equals(鞋")) {shoesList.add(鞋子);鞋=空;//<===== 添加这个}}


原始答案

你的代码是:

} else if (startElement.getName().getLocalPart().equals("title")){xmlEvent = reader.nextEvent();shoes.setTitle(xmlEvent.asCharacters().getData());

问题是代码没有检查如果事件跟在 START_ELEMENT 事件之后的类型.可能是这样的:

  • 元素很可能是空的,即<title/><title><title/>,在这种情况下下一个事件是 END_ELEMENTasCharacters() 返回 null.

  • 元素有注释,例如<title><!-- 没有标题--><title/>,在这种情况下,下一个事件是 COMMENT.p>

  • 元素具有混合内容,例如<title>foo<![CDATA[bar]]><title/>,在这种情况下,下一个事件不是全文.

检索元素的文本内容是如此常见,以至于他们为此添加了一个辅助方法:getElementText():

<块引用>

读取纯文本元素的内容.前提条件:当前事件是START_ELEMENT.后置条件:当前事件是对应的END_ELEMENT.

抛出:
XMLStreamException - 如果当前事件不是 START_ELEMENT 或者遇到非文本元素

这意味着你的代码应该是:

} else if (startElement.getName().getLocalPart().equals("title")) {shoes.setTitle(reader.getElementText());

I'm trying to write a StAX XML Parser in Java, but always get NullPointerException error. Please help me to solve this issue. Full problem:

Exception in thread "main" java.lang.NullPointerException at org.example.shoesshop.parser.STAXParser.parseXMLfile(STAXParser.java:68) at org.example.shoesshop.parser.STAXParser.main(STAXParser.java:101)

Here's a class for StAX Parser:

public class STAXParser extends DefaultHandler {
    private static List<Shoes> parseXMLfile(String fileName){
        List<Shoes> shoesList = new ArrayList<>();
        Shoes shoes = null;
        XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
        try {
            XMLEventReader reader = xmlInputFactory.createXMLEventReader(new FileInputStream(fileName));
            while (reader.hasNext()){
                XMLEvent xmlEvent = reader.nextEvent();
                if(xmlEvent.isStartElement()){
                    StartElement startElement = xmlEvent.asStartElement();
                    if(startElement.getName().getLocalPart().equals("Shoes")){
                        shoes = new Shoes();
                        Attribute idAttr = startElement.getAttributeByName(new QName("id"));
                        if(idAttr != null){
                            shoes.setId(Integer.parseInt(idAttr.getValue()));
                        }
                    } else if (startElement.getName().getLocalPart().equals("title")){
                        xmlEvent = reader.nextEvent();
                        shoes.setTitle(xmlEvent.asCharacters().getData()); // error line 68
                    } else if (startElement.getName().getLocalPart().equals("brand")){
                        xmlEvent = reader.nextEvent();
                        shoes.setBrand(Brand.fromValue(xmlEvent.asCharacters().getData()));
                    } else if (startElement.getName().getLocalPart().equals("category")){
                        xmlEvent = reader.nextEvent();
                        shoes.setCategory(Category.fromValue(xmlEvent.asCharacters().getData()));
                    } else if (startElement.getName().getLocalPart().equals("season")){
                        xmlEvent = reader.nextEvent();
                        shoes.setSeason(Season.fromValue(xmlEvent.asCharacters().getData()));
                    } else if (startElement.getName().getLocalPart().equals("price")){
                        xmlEvent = reader.nextEvent();
                        shoes.setPrice(Double.parseDouble(xmlEvent.asCharacters().getData()));
                    }
                }
                if(xmlEvent.isEndElement()){
                    EndElement endElement = xmlEvent.asEndElement();
                    if(endElement.getName().getLocalPart().equals("Shoes")){
                        shoesList.add(shoes);
                    }
                }
            }
        } catch (FileNotFoundException | XMLStreamException exc) {
            exc.printStackTrace();
        } return shoesList;
    }

    public static void main(String[] args) throws Exception {
        System.out.println("STAX Parser");
        System.out.println();
        System.out.println("Result: 
");
        System.out.println();
        String fileName = "ShoesShop.xml";
        List<Shoes> shoesList = parseXMLfile(fileName); //error line 101
        for (Shoes shoes:shoesList){
            System.out.println(shoes.toString());
        }
    }

}

Here's an XML-file

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type = "text/xsl" href = "ShoesShop.xsl"?>

<ss:ShoesShop xmlns:ss="http://www.example.org/ShoesShop" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.example.org/ShoesShop ShoesShop.xsd ">
  <ss:shoes id="1" stock="true">
    <ss:title>Baltrum</ss:title>
    <ss:brand>Gucci</ss:brand>
    <ss:category>Boots</ss:category>
    <ss:season>fall</ss:season>
    <ss:gender>
      <ss:male>male</ss:male>
    </ss:gender>
    <ss:details>
      <ss:highlights>Highlights text 1</ss:highlights>
      <ss:composition>Composition text 1</ss:composition>
    </ss:details>
    <ss:price>734.0</ss:price>
  </ss:shoes>
  
  
  <ss:shoes id="2" stock="true" mostWanted = "true">
    <ss:title>Amalfi</ss:title>
    <ss:brand>Dior</ss:brand>
    <ss:category>Mules</ss:category>
    <ss:season>winter</ss:season>
    <ss:gender>
      <ss:female>female</ss:female>
    </ss:gender>
    <ss:details>
      <ss:highlights>Highlights text 2</ss:highlights>
      <ss:composition>Composition text 2</ss:composition>
    </ss:details>
    <ss:price>364.0</ss:price>
  </ss:shoes>
  
  <ss:shoes id="3" stock="true" mostWanted = "true">
    <ss:title>Korfu</ss:title>
    <ss:brand>Mary Katrantzou</ss:brand>
    <ss:category>Sneakers</ss:category>
    <ss:season>spring</ss:season>
    <ss:gender>
      <ss:female>female</ss:female>
    </ss:gender>
    <ss:details>
      <ss:highlights>Highlights text 3</ss:highlights>
      <ss:composition>Composition text 3</ss:composition>
    </ss:details>
    <ss:price>173.0</ss:price>
  </ss:shoes>
</ss:ShoesShop>

Also here's a Java class for Shoes

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Shoes", propOrder = {
    "title",
    "brand",
    "category",
    "season",
    "gender",
    "details",
    "price"
})
public class Shoes
    extends Entity
{
    @XmlElement(required = true)
    protected String title;
    @XmlElement(required = true)
    @XmlSchemaType(name = "string")
    protected Brand brand;
    @XmlElement(required = true)
    @XmlSchemaType(name = "string")
    protected Category category;
    @XmlElement(required = true)
    @XmlSchemaType(name = "string")
    protected Season season;
    @XmlElement(required = true)
    protected Shoes.Gender gender;
    @XmlElement(required = true)
    protected Shoes.Details details;
    protected double price;
    @XmlAttribute(name = "stock", required = true)
    protected boolean stock;
    @XmlAttribute(name = "mostWanted")
    protected Boolean mostWanted;

    public String getTitle() {
        return title;
    }

    public void setTitle(String value) {
        this.title = value;
    }
    
    public Brand getBrand(){
        return brand;
    }
    
    public void setBrand(Brand value){
        this.brand = value;
    }
    
    public Category getCategory(){
        return category;
    }
    
    public void setCategory(Category value){
        this.category = value;
    }
    
    public Season getSeason(){
        return season;
    }
    
    public void setSeason(Season value) {
        this.season = value;
    }

    public Shoes.Gender getGender() {
        return gender;
    }

    public void setGender(Shoes.Gender value) {
        this.gender = value;
    }

    public Shoes.Details getDetails() {
        return details;
    }

    public void setDetails(Shoes.Details value) {
        this.details = value;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double value) {
        this.price = value;
    }

    public boolean isStock() {
        return stock;
    }

    public void setStock(boolean value) {
        this.stock = value;
    }

    public Boolean isMostWanted() {
        return mostWanted;
    }

    public void setMostWanted(Boolean value) {
        this.mostWanted = value;
    }

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {

    })
    public static class Details {

        @XmlElement(required = true)
        protected String highlights;
        @XmlElement(required = true)
        protected String composition;

        public String getHighlights() {
            return highlights;
        }

        public void setHighlights(String value) {
            this.highlights = value;
        }

        public String getComposition() {
            return composition;
        }

        public void setComposition(String value) {
            this.composition = value;
        }

    }

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "u043cu0443u0436u0441u043au043eu0439Oru0416u0435u043du0441u043au0438u0439"
    })
    public static class Gender {

        @XmlElementRefs({
            @XmlElementRef(name = "u0436u0435u043du0441u043au0438u0439", namespace = "http://www.example.org/ShoesShop", type = JAXBElement.class, required = false),
            @XmlElementRef(name = "u043cu0443u0436u0441u043au043eu0439", namespace = "http://www.example.org/ShoesShop", type = JAXBElement.class, required = false)
        })
        protected List<JAXBElement<String>> maleOrFemale;

        public List<JAXBElement<String>> getMaleOrFemale() {
            if (maleOrFemale == null) {
                maleOrFemale = new ArrayList<JAXBElement<String>>();
            }
            return this.maleOrFemale;
        }

    }
    
    @Override
    public String toString(){
        StringBuilder builder = new StringBuilder();
        builder.append("[title=");
        builder.append(title);
        builder.append(", brand=");
        builder.append(brand);
        builder.append(", category=");
        builder.append(category);
        builder.append(", season=");
        builder.append(season);
        builder.append(", price=");
        builder.append(price);
        builder.append("]");
        return builder.toString();
    }

}

Also I need to know how to write a received data into a new XML-file.

解决方案

UPDATED: Comment to original answer:

It doesn't work, it gives the same error

That means the problem is because the shoes variable is null, as would have easily been seen with a debugger. Using a debugger would have saved us all a lot of time, so please start using one.

In order for shoes to be null, it appears that the code encountered a <title> element that is not a child of a Shoes element.

To fix the code, add a null-check, and also set shoes = null at the end of processing the Shoes element:

} else if (startElement.getName().getLocalPart().equals("title")) {
    if (shoes != null) { // <===== ADD THIS
        shoes.setTitle(reader.getElementText()); // <===== Fix this (see original answer)
    }

if (xmlEvent.isEndElement()) {
    EndElement endElement = xmlEvent.asEndElement();
    if (endElement.getName().getLocalPart().equals("Shoes")) {
        shoesList.add(shoes);
        shoes = null; // <===== ADD THIS
    }
}


ORIGINAL ANSWER

Your code is:

} else if (startElement.getName().getLocalPart().equals("title")){
    xmlEvent = reader.nextEvent();
    shoes.setTitle(xmlEvent.asCharacters().getData());

The problem is that the code isn't checking what type if event follows the START_ELEMENT event. It could be that:

  • Most likely, the element is empty, i.e. <title/> or <title><title/>, in which case the next event is an END_ELEMENT, and asCharacters() returned null.

  • The element has a comment, e.g. <title><!-- there is no title --><title/>, in which case the next event is a COMMENT.

  • The element has mixed content, e.g. <title>foo<![CDATA[bar]]><title/>, in which case the next event is not the full text.

Retrieving the text content of an element is such a common thing that they added a helper method for that: getElementText():

Reads the content of a text-only element. Precondition: the current event is START_ELEMENT. Postcondition: The current event is the corresponding END_ELEMENT.

Throws:
XMLStreamException - if the current event is not a START_ELEMENT or if a non text element is encountered

Which means that your code should be:

} else if (startElement.getName().getLocalPart().equals("title")) {
    shoes.setTitle(reader.getElementText());

这篇关于为什么在运行 StAX Parser 时出现 NullPointerException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

How to send data to COM PORT using JAVA?(如何使用 JAVA 向 COM PORT 发送数据?)
How to make a report page direction to change to quot;rtlquot;?(如何使报表页面方向更改为“rtl?)
Use cyrillic .properties file in eclipse project(在 Eclipse 项目中使用西里尔文 .properties 文件)
Is there any way to detect an RTL language in Java?(有没有办法在 Java 中检测 RTL 语言?)
How to load resource bundle messages from DB in Java?(如何在 Java 中从 DB 加载资源包消息?)
How do I change the default locale settings in Java to make them consistent?(如何更改 Java 中的默认语言环境设置以使其保持一致?)