java 如何忽略 JaxB 中元素名称的大小写
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4375176/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to ignore casing of element names in JaxB
提问by tkr
As stated in the title I want to ignore casing of element names in a document.
如标题所述,我想忽略文档中元素名称的大小写。
static class XY433 {
@XmlAttribute(name = "C200")
String c200;
@XmlAttribute(name = "C215")
String c215;
@XmlAttribute(name="F001")
String f001;
@XmlAttribute(name="f001")
String lcf001; // I want to avoid this duplication
}
I tried to use the code posted by Blaise Doughan:
我尝试使用 Blaise Doughan 发布的代码:
private static class ToLowerCaseNamesStreamReaderDelegate extends StreamReaderDelegate {
public ToLowerCaseNamesStreamReaderDelegate(XMLStreamReader xsr) {
super(xsr);
}
@Override
public String getAttributeLocalName(int index) {
return super.getAttributeLocalName(index).toLowerCase();
}
@Override
public String getLocalName() {
return super.getLocalName().toLowerCase();
}
}
@XmlRootElement(name="doc")
static class Doc {
@XmlElement(name="element")
List<Element> elements;
}
static class Element {
@XmlAttribute(name = "abc")
String abc;
}
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newInstance();
XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("LowerCaseElementNamesFilterTest.xml"));
Unmarshaller u = JAXBContext.newInstance(Doc.class).createUnmarshaller();
//Do unmarshalling
Doc doc = (Doc) u.unmarshal(new ToLowerCaseNamesStreamReaderDelegate(xsr));
System.out.println(doc.elements.get(0).abc);
System.out.println(doc.elements.get(1).abc);
System.out.println(doc.elements.get(2).abc);
}
This actually did not work.
这实际上不起作用。
null
2
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
at java.util.ArrayList.RangeCheck(ArrayList.java:546)
at java.util.ArrayList.get(ArrayList.java:321)
at com.hre.commons.tec.xml.LowerCaseElementNamesFilter.main(LowerCaseElementNamesFilter.java:58)
For this XML:
对于此 XML:
<doc>
<Element ABC="1"></Element>
<element Abc="1"></element>
<element abc="2"></element>
</doc>
回答by bdoughan
You could map all your properties to lower case node names, and then wrap an XMLStreamReader to call toLowerCase() on all attribute/element names it returned. Then unmarshal from that XMLStreamReader.
您可以将所有属性映射到小写节点名称,然后包装一个 XMLStreamReader 以在它返回的所有属性/元素名称上调用 toLowerCase()。然后从那个 XMLStreamReader 解组。
I have recently added an enhance request for EclipseLink JAXB (MOXy) for this issue, feel free to provide additional information:
我最近为此问题添加了对 EclipseLink JAXB (MOXy) 的增强请求,请随时提供其他信息:
Object Model
对象模型
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Customer {
private int id;
private String name;
private Address address;
@XmlAttribute
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
public class Address {
private String street;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}
Demo Code
演示代码
import java.io.FileInputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.util.StreamReaderDelegate;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Customer.class);
XMLInputFactory xif = XMLInputFactory.newInstance();
XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("input.xml"));
xsr = new MyStreamReaderDelegate(xsr);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Customer customer = (Customer) unmarshaller.unmarshal(xsr);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(customer, System.out);
}
private static class MyStreamReaderDelegate extends StreamReaderDelegate {
public MyStreamReaderDelegate(XMLStreamReader xsr) {
super(xsr);
}
@Override
public String getAttributeLocalName(int index) {
return super.getAttributeLocalName(index).toLowerCase();
}
@Override
public String getLocalName() {
return super.getLocalName().toLowerCase();
}
}
}
Will read these XML documents:
将读取这些 XML 文档:
<CUSTOMER ID="1">
<NAME>Jane Doe</NAME>
<ADDRESS>
<STREET>123 A Street</STREET>
</ADDRESS>
</CUSTOMER>
<CuSToMeR Id="1">
<NaMe>Jane Doe</NAME>
<AdDrEsS>
<STREET>123 A Street</STREET>
</AdDRrEsS>
</CuSToMeR>
And write the following XML:
并编写以下 XML:
<customer id="1">
<address>
<street>123 A Street</street>
</address>
<name>Jane Doe</name>
</customer>
Below is a link to a more detailed example:
以下是更详细示例的链接:
UPDATE
更新
Your code works in my environment (JDK 1.6.0_20 with both the included JAXB, and EclipseLink JAXB (MOXy) 2.2, I'm also using the default implementation of StAX). When I run your example:
您的代码适用于我的环境(JDK 1.6.0_20 与包含的 JAXB 和 EclipseLink JAXB (MOXy) 2.2,我也在使用 StAX 的默认实现)。当我运行你的例子时:
import java.io.FileInputStream;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.util.StreamReaderDelegate;
public class Example {
private static class ToLowerCaseNamesStreamReaderDelegate extends StreamReaderDelegate {
public ToLowerCaseNamesStreamReaderDelegate(XMLStreamReader xsr) {
super(xsr);
}
@Override
public String getAttributeLocalName(int index) {
return super.getAttributeLocalName(index).toLowerCase();
}
@Override
public String getLocalName() {
return super.getLocalName().toLowerCase();
}
}
@XmlRootElement(name="doc")
static class Doc {
@XmlElement(name="element")
List<Element> elements;
}
static class Element {
@XmlAttribute(name = "abc")
String abc;
}
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newInstance();
XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("LowerCaseElementNamesFilterTest.xml"));
Unmarshaller u = JAXBContext.newInstance(Doc.class).createUnmarshaller();
//Do unmarshalling
Doc doc = (Doc) u.unmarshal(new ToLowerCaseNamesStreamReaderDelegate(xsr));
System.out.println(doc.elements.get(0).abc);
System.out.println(doc.elements.get(1).abc);
System.out.println(doc.elements.get(2).abc);
}
}
I get the following output:
我得到以下输出:
1
1
2
UPDATE #2
更新 #2
To address:
讲话:
Exception in thread "main" javax.xml.bind.UnmarshalException - with linked exception: [javax.xml.bind.UnmarshalException: Namespace URIs and local names to the unmarshaller needs to be interned.] at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:425) at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:362) at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:332)
线程“main”中的异常 javax.xml.bind.UnmarshalException - 带有链接异常:[javax.xml.bind.UnmarshalException:命名空间 URI 和解组器的本地名称需要实习。] 在 com.sun.xml.bind。 v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:425) at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:362) at com.bind.sun.xml v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:332)
Have you tried modifying the delegate?:
您是否尝试过修改委托?:
@Override
public String getAttributeLocalName(int index) {
return super.getAttributeLocalName(index).toLowerCase().intern();
}
@Override
public String getLocalName() {
return super.getLocalName().toLowerCase().intern();
}
回答by Ralph
Encounter the similar problem.
My solution is to add @XmlAdpater
on the model entity, which refers to your own XMLAdapter
, this would give a flexible customization on the marshall/unmarshall.
遇到类似的问题。我的解决方案是添加@XmlAdpater
模型实体,它指的是您自己的XMLAdapter
,这将提供对 marshall/unmarshall 的灵活定制。
回答by Mustafa Basaran
I am using moxy 2.7.1 version and it is working fine with UnmarshallerProperty as below.
我使用的是 moxy 2.7.1 版本,它与 UnmarshallerProperty 一起工作正常,如下所示。
unmarshaller.setProperty(UnmarshallerProperties.UNMARSHALLING_CASE_INSENSITIVE, true);