3

我有一个对象的 xml 表示,比如 OrderList(有列表)订单,每个订单都有一个商品列表。

我想验证我的商品,如果无效,我想从订单中删除它们。如果所有商品都无效,那么我从订单列表中删除该订单。

我已经能够验证 Orderlist

JAXBContext jaxbContext = JAXBContext.newInstance("com.jaxb");
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new File(XSD));
JAXBSource source = new JAXBSource(jaxbContext, orderList);
Validator validator = schema.newValidator();
DataFeedErrorHandler handler = new DataFeedErrorHandler();
validator.setErrorHandler(handler);
validator.validate(source);

我无法找到验证商品的方法。

就像是

for(Order order: orderList){
    for(Commodity commodity: order.getCommodity()){
       if(!isCommodityValid(commodity)){
         // mark for removal
       }
    }
}

任何帮助将不胜感激。

4

1 回答 1

2

TL;博士

您可以做一个虚拟编组并利用 JAXB 验证机制,而不是javax.xml.validation直接使用这些机制。

杠杆Marshaller.Listener& ValidationEventHandler(商品验证器)

对于这个例子,我们将利用各个方面Marshaller.ListenerValidationEventHandler完成用例。

  • Marshal.Listener- 这将为每个正在编组的对象调用。我们可以使用它来缓存Order我们可能需要从中删除实例的实例Commodity
  • ValidationEventHandler这将使我们能够访问在marshal操作期间验证出现的每个问题。对于每个问题,它将传递一个ValidationEvent. 这ValidationEvent将包含一个ValidationEventLocator我们可以从中获取有问题的对象被编组的对象。
import javax.xml.bind.*;

public class CommodityValidator extends Marshaller.Listener implements ValidationEventHandler {

    private Order order;

    @Override
    public void beforeMarshal(Object source) {
        if(source instanceof Order) {
            // If we are marshalling an Order Store It
            order = (Order) source;
        }
    }

    @Override
    public boolean handleEvent(ValidationEvent event) {
        if(event.getLocator().getObject() instanceof Commodity) {
            // If the Error was Caused by a Commodity Object Remove it from the Order
            order.setCommodity(null);
            return true;
        }
        return false;
    }

}

演示代码

可以运行以下代码来证明一切正常。

import java.io.File;
import javax.xml.XMLConstants;
import javax.xml.bind.*;
import javax.xml.validation.*;
import org.xml.sax.helpers.DefaultHandler;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Orders.class);

        // STEP 1 - Build the Object Model
        Commodity commodity1 = new Commodity();
        commodity1.setId("1");
        Order order1 = new Order();
        order1.setCommodity(commodity1);

        Commodity commodityInvalid = new Commodity();
        commodityInvalid.setId("INVALID");
        Order order2 = new Order();
        order2.setCommodity(commodityInvalid);

        Commodity commodity3 = new Commodity();
        commodity3.setId("3");
        Order order3 = new Order();
        order3.setCommodity(commodity3);

        Orders orders = new Orders();
        orders.getOrderList().add(order1);
        orders.getOrderList().add(order2);
        orders.getOrderList().add(order3);

        // STEP 2 - Check that all the Commodities are Set
        System.out.println("\nCommodities - Before Validation");
        for(Order order : orders.getOrderList()) {
            System.out.println(order.getCommodity());
        }

        // STEP 3 - Create the XML Schema
        SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = sf.newSchema(new File("src/forum16953248/schema.xsd"));

        // STEP 4 - Perform Validation with the Marshal Operation
        Marshaller marshaller = jc.createMarshaller();

        // STEP 4a - Set the Schema on the Marshaller
        marshaller.setSchema(schema);

        // STEP 4b - Set the CommodityValidator as the Listener and EventHandler
        CommodityValidator commodityValidator = new CommodityValidator();
        marshaller.setListener(commodityValidator);
        marshaller.setEventHandler(commodityValidator);

        // STEP 4c - Marshal to Anything
        marshaller.marshal(orders, new DefaultHandler());

        // STEP 5 - Check that the Invalid Commodity was Removed
        System.out.println("\nCommodities - After Validation");
        for(Order order : orders.getOrderList()) {
            System.out.println(order.getCommodity());
        }
    }

}

输出

下面是运行演示代码的输出。节点在封送操作之后如何移除无效商品。

Commodities - Before Validation
forum16953248.Commodity@3bb505fe
forum16953248.Commodity@699c8551
forum16953248.Commodity@22f4bf02

Commodities - After Validation
forum16953248.Commodity@3bb505fe
null
forum16953248.Commodity@22f4bf02

XML 架构 (schema.xsd)

下面是用于此示例的 XML 模式。

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
    <element name="orders">
        <complexType>
            <sequence>
                <element name="order" minOccurs="0" maxOccurs="unbounded">
                    <complexType>
                        <sequence>
                            <element name="commodity">
                                <complexType>
                                    <attribute name="id" type="int"/>
                                </complexType>
                            </element>
                        </sequence>
                    </complexType>
                </element>
            </sequence>
        </complexType>
    </element>
</schema>

JAVA模型

下面是我在这个例子中使用的对象模型。

订单

import java.util.*;
import javax.xml.bind.annotation.*;

@XmlRootElement
public class Orders {

    private List<Order> orderList = new ArrayList<Order>();

    @XmlElement(name="order")
    public List<Order> getOrderList() {
        return orderList;
    }

}

命令

public class Order {

    private Commodity commodity;

    public Commodity getCommodity() {
        return commodity;
    }

    public void setCommodity(Commodity commodity) {
        this.commodity = commodity;
    }

}

商品

import javax.xml.bind.annotation.*;

public class Commodity {

    private String id;

    @XmlAttribute
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

}
于 2013-06-13T15:20:45.343 回答