对于某些XML模式来说,它是一组严格的规则,用于规定XML文档的结构方式。 但是对于其他人来说,通常的准则是指出XML的外观。 这意味着有时出于某些原因人们希望接受不符合XML模式的输入。 在此示例中,我将演示如何利用SAX XMLFilter来完成此操作。
Java模型
下面是将用于此示例的Java模型。
顾客
package blog.namespace.sax;import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement
public class Customer {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}}
包装信息
我们将使用包级别@XmlSchema批注为模型指定名称空间限定。
@XmlSchema(namespace='http://www.example.com/customer',elementFormDefault=XmlNsForm.QUALIFIED)
package blog.namespace.sax;import javax.xml.bind.annotation.*;
XML输入(input.xml)
即使我们的元数据指定所有元素都应使用命名空间(http://www.example.com/customer)限定,我们的输入文档也不是使用命名空间限定的。 在解组操作期间,将使用XMLFilter添加名称空间。
<?xml version='1.0' encoding='UTF-8'?>
<customer><name>Jane Doe</name>
</customer>
XMLFilter(NamespaceFilter)
创建XMLFilter的最简单方法是扩展XMLFilterImpl 。 对于我们的用例,我们将覆盖startElement和endElement方法。 在这些方法的每一个中,我们将调用相应的super方法,并将默认名称空间作为URI参数传递。
package blog.namespace.sax;import org.xml.sax.*;
import org.xml.sax.helpers.XMLFilterImpl;public class NamespaceFilter extends XMLFilterImpl {private static final String NAMESPACE = 'http://www.example.com/customer';@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {super.endElement(NAMESPACE, localName, qName);}@Overridepublic void startElement(String uri, String localName, String qName,Attributes atts) throws SAXException {super.startElement(NAMESPACE, localName, qName, atts);}}
演示版
在下面的演示代码中,我们将对XML文档进行SAX解析。 XMLReader将包装在我们的XMLFilter中 。 我们将利用JAXB的UnmarshallerHandler作为ContentHandler 。 解析完成后,我们可以向UnmarshallerHandler请求生成的Customer对象。
package blog.namespace.sax;import javax.xml.bind.*;
import javax.xml.parsers.*;
import org.xml.sax.*;public class Demo {public static void main(String[] args) throws Exception {// Create the JAXBContextJAXBContext jc = JAXBContext.newInstance(Customer.class);// Create the XMLFilterXMLFilter filter = new NamespaceFilter();// Set the parent XMLReader on the XMLFilterSAXParserFactory spf = SAXParserFactory.newInstance();SAXParser sp = spf.newSAXParser();XMLReader xr = sp.getXMLReader();filter.setParent(xr);// Set UnmarshallerHandler as ContentHandler on XMLFilterUnmarshaller unmarshaller = jc.createUnmarshaller();UnmarshallerHandler unmarshallerHandler = unmarshaller.getUnmarshallerHandler();filter.setContentHandler(unmarshallerHandler);// Parse the XMLInputSource xml = new InputSource('src/blog/namespace/sax/input.xml');filter.parse(xml);Customer customer = (Customer) unmarshallerHandler.getResult();// Marshal the Customer object back to XMLMarshaller marshaller = jc.createMarshaller();marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);marshaller.marshal(customer, System.out);}}
输出量
以下是运行演示代码的输出。 注意输出如何包含基于元数据的名称空间限定。
<?xml version='1.0' encoding='UTF-8'?>
<customer xmlns='http://www.example.com/customer'><name>Jane Doe</name>
</customer>
进一步阅读
如果您喜欢这篇文章,那么您可能也会对以下内容感兴趣:
- JAXB和命名空间
- 防止JAXB中的实体扩展攻击
参考:在Java XML&JSON Binding博客上,我们的JCG合作伙伴 Blaise Doughan 在JAXB Unmarshal期间应用名称空间 。
翻译自: https://www.javacodegeeks.com/2012/11/applying-a-namespace-during-jaxb-unmarshal.html