【问题标题】:SAX XML File Parsing (JAVA)SAX XML 文件解析 (JAVA)
【发布时间】:2012-03-22 15:25:16
【问题描述】:

我必须创建一个类来从我创建的名为 invoice.xml 的 xml 中提取数据。在 xml 中,客户可能会购买多个商品。打印提取的数据时的问题是,如果是这种情况,则只会打印客户购买的最后一个元素。 有人可以提出解决方案吗?我还将附上我的 xml 文件,因为我很确定这就是问题所在。

SAXParserExample.java

package Attempt2;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SAXParserExample extends DefaultHandler {

    List<Invoice> myInvoices;
    private String tempVal;
    private Invoice tempInv;

    public SAXParserExample() {
        myInvoices = new ArrayList<Invoice>();
    }

    public void runExample() {
        parseDocument();
        printData();
    }

    private void parseDocument() {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        try {
            SAXParser sp = spf.newSAXParser();
            sp.parse("invoice.xml", this);

        } catch (SAXException se) {
            se.printStackTrace();
        } catch (ParserConfigurationException pce) {
            pce.printStackTrace();
        } catch (IOException ie) {
            ie.printStackTrace();
        }
    }

    private void printData() {
        System.out.println("\n\n\tNo of Invoices '" + myInvoices.size()
                + "'.\n");
        Iterator<Invoice> it = myInvoices.iterator();
        while (it.hasNext()) {
            System.out.println("\n\t" + it.next().toString());
        }
    }

    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        tempVal = "";
        if (qName.equalsIgnoreCase("Invoice")) {
            tempInv = new Invoice();
        }
    }

    public void characters(char[] ch, int start, int length)
            throws SAXException {
        tempVal = new String(ch, start, length);
    }

    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        if (qName.equalsIgnoreCase("invoice")) {
            myInvoices.add(tempInv);
        } else if (qName.equalsIgnoreCase("invoicenum")) {
            tempInv.setInvoiceNum(tempVal);
        } else if (qName.equalsIgnoreCase("title")) {
            tempInv.setTitle((tempVal));
        } else if (qName.equalsIgnoreCase("name")) {
            tempInv.setName((tempVal));
        } else if (qName.equalsIgnoreCase("street")) {
            tempInv.setStreet((tempVal));
        } else if (qName.equalsIgnoreCase("city")) {
            tempInv.setCity((tempVal));
        } else if (qName.equalsIgnoreCase("county")) {
            tempInv.setCounty((tempVal));
        } else if (qName.equalsIgnoreCase("postal")) {
            tempInv.setPostal((tempVal));
        } else if (qName.equalsIgnoreCase("description")) {
            tempInv.setDescription((tempVal));
        } else if (qName.equalsIgnoreCase("price")) {
            tempInv.setPrice((tempVal));
        } else if (qName.equalsIgnoreCase("quantity")) {
            tempInv.setQuantity((tempVal));
        }
    }

    public static void main(String[] args) {
        SAXParserExample spe = new SAXParserExample();
        spe.runExample();
    }

}

invoice.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE people SYSTEM "invoice.dtd">
<invoices> 
    <invoice>
        <invoicenum>Invoice# 12345</invoicenum>
        <address>
            <title>Customer Address</title>
            <name>William Owen</name>
            <street>99 Anywhere Avenue</street>
            <city>Bangor</city>
            <county>Gwynedd</county>
            <postal>LL57 3JP</postal>
        </address>
        <items>
            <order>Items Ordered</order>
            <item>
                <description>Ink Jet Refill Kit</description>
                <price>29.50</price>
                <quantity>2</quantity>
            </item>
            <item>
                <description>4-Port Mini Hub</description>
                <price>19.95</price>
                <quantity>1</quantity>
            </item>
        </items>
    </invoice>
    <invoice>
        <invoicenum>Invoice# 12346</invoicenum>
        <address>
            <title>Customer Address</title>
            <name>Alex Gavra</name>
            <street>14 Menai View Terrace</street>
            <city>Bangor</city>
            <county>Gwynedd</county>
            <postal>LL57 2HF</postal>
        </address>
        <items>
            <order>Items Ordered</order>
            <item>
                <description>200GB External Disk Drive</description>
                <price>83.50</price>
                <quantity>1</quantity>
            </item>
        </items>
    </invoice>
    <invoice>
        <invoicenum>Invoice# 12347</invoicenum>
        <address>
            <title>Customer Address</title>
            <name>Mark Reeves</name>
            <street>Neuadd Llys Trifan</street>
            <city>Bangor</city>
            <county>Gwynedd</county>
            <postal>LL57 2JS</postal>
        </address>
        <items>
            <order>Items Ordered</order>
            <item>
                <description>19 Inch LCD Monitor LG</description>
                <price>120</price>
                <quantity>1</quantity>
            </item>
            <item>
                <description>Wireless mouse Laser Microsoft</description>
                <price>17.55</price>
                <quantity>1</quantity>
            </item>
        </items>
    </invoice>
    <invoice>
        <invoicenum>Invoice# 12348</invoicenum>
        <address>
            <title>Customer Address</title>
            <name>Nick Murray</name>
            <street>10 Some Street</street>
            <city>London</city>
            <county>London</county>
            <postal>WC1</postal>
        </address>
        <items>
            <order>Items Ordered</order>
            <item>
                <description>Microsoft keyboard SF200</description>
                <price>60.50</price>
                <quantity>1</quantity>
            </item>
            <item>
                <description>Screen cleaner spray</description>
                <price>4.59</price>
                <quantity>3</quantity>
            </item>
            <item>
                <description>Office chair</description>
                <price>149.99</price>
                <quantity>1</quantity>
            </item>
        </items>
    </invoice>
    <invoice>
        <invoicenum>Invoice# 12349</invoicenum>
        <address>
            <title>Customer Address</title>
            <name>Michael Jones</name>
            <street>Somewhere Street 18</street>
            <city>London</city>
            <county>London</county>
            <postal>E17</postal>
        </address>
        <items>
            <order>Items Ordered</order>
            <item>
                <description>PLX Elastic Bands</description>
                <price>15.73</price>
                <quantity>1</quantity>
            </item>
        </items>
    </invoice>
</invoices>

另外,在创建了我的 java 类之后,我在插入了多个项目的 xml 文档中收到以下消息:

我对 DTD 知之甚少,但这是我所写的:

invoice.dtd

<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT invoices (invoice*)>
<!ELEMENT invoice (invoicenum, address, items)>
<!ELEMENT address (title, name, street, city, county, postal)>
<!ELEMENT items (order, item)>
<!ELEMENT item (description, price, quantity)>

<!ELEMENT invoicenum (#PCDATA)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT street (#PCDATA)>
<!ELEMENT city (#PCDATA)>
<!ELEMENT county (#PCDATA)>
<!ELEMENT postal (#PCDATA)>
<!ELEMENT order (#PCDATA)>
<!ELEMENT description (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ELEMENT quantity (#PCDATA)>

另外,我附上了 Invoice.java 类,以防有提示可以解决这个问题。

package Attempt2;

public class Invoice {

    private String invoicenum;
    private String title;
    private String name;
    private String street;
    private String city;
    private String county;
    private String postal;
    private String order;
    private String description;
    private String price;
    private String quantity;

    public Invoice() {
        System.out.println("\n\t No Arg Invoice Constructor Called…");
    }

    public Invoice(String invoicenum, String title, String name, String street,
            String city, String county, String postal, String order,
            String description, String price, String quantity) {
        System.out.println("\n\t 4-Argument Invoice Constructor Called…");
        this.invoicenum = invoicenum;
        this.title = title;
        this.name = name;
        this.street = street;
        this.city = city;
        this.county = county;
        this.postal = postal;
        this.order = order;
        this.description = description;
        this.price = price;
        this.quantity = quantity;

    }

    public String getInvoiceNum() {
        return invoicenum;
    }

    public void setInvoiceNum(String invoicenum) {
        this.invoicenum = invoicenum;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    // street
    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    // city;
    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    // county
    public String getCounty() {
        return county;
    }

    public void setCounty(String county) {
        this.county = county;
    }

    // postal
    public String getPostal() {
        return postal;
    }

    public void setPostal(String postal) {
        this.postal = postal;
    }

    // order
    public String getOrder() {
        return order;
    }

    public void setOrder(String order) {
        this.order = order;
    }

    // description
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    // price
    public String getPrice() {
        return price;
    }

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

    // quantity
    public String getQuantity() {
        return quantity;
    }

    public void setQuantity(String quantity) {
        this.quantity = quantity;
    }

    /**
    private String title;
    private String order;
     */
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("Invoice Details \n---------------------------------\n");
        sb.append("Invoice Number:" + getInvoiceNum()+"\n");
        sb.append("Name:" + getName()+"\n");
        sb.append("Street:" + getStreet()+"\n");
        sb.append("City:" + getCity()+"\n");
        sb.append("County:" + getCounty()+"\n");
        sb.append("Postal Code:" + getPostal()+"\n");
        sb.append("Item Description:" + getDescription()+"\n");
        sb.append("Price:" + getPrice()+"\n");
        sb.append("Quantity:" + getQuantity()+"\n");
        return sb.toString();
    }
}

【问题讨论】:

  • 我建议您使用框架,例如 Apache Digester,来读取 XML 文件而不是自制代码。
  • 不幸的是我使用Java是项目的要求..
  • 嗯,Apache Digester 是一个 Java 库。
  • 这里不需要使用库。他已经有了工作代码。这将是浪费时间。另外,他可以使用 JAXB 而不是手工构建的 SAX 解析器,而不是使用 3rd 方库。如果您不需要,则无需引入 3rd 方依赖项。 (JAXB 在 Java 1.6 的 Update 14 左右被添加到 JDK)
  • 您的 DTD 是否允许多个项目?就我个人而言,我发现 XmlSchemas 更容易阅读。你能提供你的 DTD 吗?

标签: java xml parsing sax invoice


【解决方案1】:

DTD 说一个 元素只能有一个 元素和一个 元素。在 XML 文件中,您的 带有 两个 元素,这在 DTD 方面是错误的。

如果 可能有多个 元素,一种解决方案是更改 DTD 的以下行

XML 文件中的以下行也是错误的:

应该是

em>发票 SYSTEM "invoice.dtd">

DTD 中没有 people 元素定义

【讨论】:

    【解决方案2】:

    由于我完全误解了您的问题并导致您整天误入歧途,因此我已修复您的解析器,以便它将项目作为单独的对象处理,现在您的发票包含项目列表。对不起!

    public class Item {
    String description;
    String price;
    String quantity;
    
    public String getDescription() {
        return description;
    }
    
    public void setDescription(String description) {
        this.description = description;
    }
    
    public String getPrice() {
        return price;
    }
    
    public void setPrice(String price) {
        this.price = price;
    }
    
    public String getQuantity() {
        return quantity;
    }
    
    public void setQuantity(String quantity) {
        this.quantity = quantity;
    }
    
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("Item");
        sb.append("{description='").append(description).append('\'');
        sb.append(", price='").append(price).append('\'');
        sb.append(", quantity='").append(quantity).append('\'');
        sb.append('}');
        return sb.toString();
    }
    

    }

    public class Invoice {
    String invoiceNum;
    String title;
    String name;
    String street;
    String city;
    String county;
    String postal;
    List<Item> items;
    
    public Invoice() {
        this.items = new ArrayList<Item>();
    }
    
    public void addItem(Item item) {
        this.items.add(item);
    }
    
    public String getCity() {
        return city;
    }
    
    public void setCity(String city) {
        this.city = city;
    }
    
    public String getCounty() {
        return county;
    }
    
    public void setCounty(String county) {
        this.county = county;
    }
    
    public String getInvoiceNum() {
        return invoiceNum;
    }
    
    public void setInvoiceNum(String invoiceNum) {
        this.invoiceNum = invoiceNum;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getPostal() {
        return postal;
    }
    
    public void setPostal(String postal) {
        this.postal = postal;
    }
    
    public String getStreet() {
        return street;
    }
    
    public void setStreet(String street) {
        this.street = street;
    }
    
    public String getTitle() {
        return title;
    }
    
    public void setTitle(String title) {
        this.title = title;
    }
    
    
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("Invoice");
        sb.append("{city='").append(city).append('\'');
        sb.append(", invoiceNum='").append(invoiceNum).append('\'');
        sb.append(", title='").append(title).append('\'');
        sb.append(", name='").append(name).append('\'');
        sb.append(", street='").append(street).append('\'');
        sb.append(", county='").append(county).append('\'');
        sb.append(", postal='").append(postal).append('\'');
        sb.append(", items=").append(items);
        sb.append('}');
        return sb.toString();
    }
    

    }

    public class SaxParserExample extends DefaultHandler {
    
    List<Invoice> myInvoices;
    private String tempVal;
    private Invoice tempInv;
    private Item tempItem;
    
    public SaxParserExample() {
        myInvoices = new ArrayList<Invoice>();
    }
    
    public void runExample() {
        parseDocument();
        printData();
    }
    
    private void parseDocument() {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        try {
            SAXParser sp = spf.newSAXParser();
            sp.parse("invoice.xml", this);
    
        } catch (SAXException se) {
            se.printStackTrace();
        } catch (ParserConfigurationException pce) {
            pce.printStackTrace();
        } catch (IOException ie) {
            ie.printStackTrace();
        }
    }
    
    private void printData() {
        System.out.println("No of Invoices '" + myInvoices.size());
        for (Invoice myInvoice : myInvoices) {
            System.out.println(myInvoice);
        }
    }
    
    public void startElement(String uri, String localName, String qName,
                             Attributes attributes) throws SAXException {
        tempVal = "";
        if ("Invoice".equalsIgnoreCase(qName)) {
            tempInv = new Invoice();
        } else if ("item".equalsIgnoreCase(qName)) {
            tempItem = new Item();
        }
    }
    
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        tempVal = new String(ch, start, length);
    }
    
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        if ("invoice".equalsIgnoreCase(qName)) {
            myInvoices.add(tempInv);
        } else if ("item".equalsIgnoreCase(qName)) {
            tempInv.addItem(tempItem);
        } else if ("invoicenum".equalsIgnoreCase(qName)) {
            tempInv.setInvoiceNum(tempVal);
        } else if ("title".equalsIgnoreCase(qName)) {
            tempInv.setTitle((tempVal));
        } else if ("name".equalsIgnoreCase(qName)) {
            tempInv.setName((tempVal));
        } else if ("street".equalsIgnoreCase(qName)) {
            tempInv.setStreet((tempVal));
        } else if ("city".equalsIgnoreCase(qName)) {
            tempInv.setCity((tempVal));
        } else if ("county".equalsIgnoreCase(qName)) {
            tempInv.setCounty((tempVal));
        } else if ("postal".equalsIgnoreCase(qName)) {
            tempInv.setPostal((tempVal));
        } else if ("description".equalsIgnoreCase(qName)) {
            tempItem.setDescription((tempVal));
        } else if ("price".equalsIgnoreCase(qName)) {
            tempItem.setPrice((tempVal));
        } else if ("quantity".equalsIgnoreCase(qName)) {
            tempItem.setQuantity((tempVal));
        }
    }
    
    public static void main(String[] args) {
        SaxParserExample spe = new SaxParserExample();
        spe.runExample();
    }
    

    }

    【讨论】:

    • 我听从了你的建议,但不幸的是这并不能解决问题:(
    • 至少我没有在我的 xml 文件中收到错误消息,但我仍然没有收到我的列表中的所有项目。
    • 有没有抛出异常?它正在查找 invoice.xml 文件,对吗?尝试通过调试器运行代码。
    • 没有任何例外,现在这变得非常奇怪。我还附加了我的 Invoice 类,以防格式中的某些内容出错并且它只是不打印项目。
    • 我用您的 Invoice bean 对其进行了测试,它对我来说仍然可以正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-19
    • 2017-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多