我有从架构创建的JAXB对象。在编组时,xml元素将使用ns2进行注释。我已经尝试过网络上存在的所有选项,但是这些选项都不起作用。我无法修改我的架构或更改package-info.java。请帮忙
答案 0 :(得分:17)
经过大量的研究和修补,我终于设法解决了这个问题。请接受我的道歉,因为没有发布原始参考文献的链接 - 有许多我没有做笔记 - 但是this一个肯定是有用的。
我的解决方案使用过滤XMLStreamWriter
,它应用空名称空间上下文。
public class NoNamesWriter extends DelegatingXMLStreamWriter {
private static final NamespaceContext emptyNamespaceContext = new NamespaceContext() {
@Override
public String getNamespaceURI(String prefix) {
return "";
}
@Override
public String getPrefix(String namespaceURI) {
return "";
}
@Override
public Iterator getPrefixes(String namespaceURI) {
return null;
}
};
public static XMLStreamWriter filter(Writer writer) throws XMLStreamException {
return new NoNamesWriter(XMLOutputFactory.newInstance().createXMLStreamWriter(writer));
}
public NoNamesWriter(XMLStreamWriter writer) {
super(writer);
}
@Override
public NamespaceContext getNamespaceContext() {
return emptyNamespaceContext;
}
}
您可以找到DelegatingXMLStreamWriter
here。
然后,您可以使用以下方法过滤编组xml
// Filter the output to remove namespaces.
m.marshal(it, NoNamesWriter.filter(writer));
我确信有更有效的机制,但我知道这个机制有效。
答案 1 :(得分:13)
对我来说,只更改package-info.java类就像魅力一样,就像zatziky所说:
package-info.java
@javax.xml.bind.annotation.XmlSchema
(namespace = "http://example.com",
xmlns = {@XmlNs(prefix = "", namespaceURI = "http://example.com")},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package my.package;
import javax.xml.bind.annotation.XmlNs;
答案 2 :(得分:5)
您可以只将命名空间写入一次。您将需要XMLStreamWriter的代理类和package-info.java。然后你会在你的代码中做到:
StringWriter stringWriter = new StringWriter();
XMLStreamWriter writer = new Wrapper((XMLStreamWriter) XMLOutputFactory
.newInstance().createXMLStreamWriter(stringWriter));
JAXBContext jaxbContext = JAXBContext.newInstance(Collection.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
jaxbMarshaller.marshal(books, writer);
System.out.println(stringWriter.toString());
代理类(重要的方法是“writeNamespace”):
class WrapperXMLStreamWriter implements XMLStreamWriter {
private final XMLStreamWriter writer;
public WrapperXMLStreamWriter(XMLStreamWriter writer) {
this.writer = writer;
}
//keeps track of what namespaces were used so that not to
//write them more than once
private List<String> namespaces = new ArrayList<String>();
public void init(){
namespaces.clear();
}
public void writeStartElement(String localName) throws XMLStreamException {
init();
writer.writeStartElement(localName);
}
public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
init();
writer.writeStartElement(namespaceURI, localName);
}
public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
init();
writer.writeStartElement(prefix, localName, namespaceURI);
}
public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
if(namespaces.contains(namespaceURI)){
return;
}
namespaces.add(namespaceURI);
writer.writeNamespace(prefix, namespaceURI);
}
// .. other delegation method, always the same pattern: writer.method() ...
}
package-info.java:
@XmlSchema(elementFormDefault=XmlNsForm.QUALIFIED, attributeFormDefault=XmlNsForm.UNQUALIFIED ,
xmlns = {
@XmlNs(namespaceURI = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi")})
package your.package;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
答案 3 :(得分:2)
您可以使用NamespacePrefixMapper
扩展名来控制用例的名称空间前缀。 JAXB参考实现和EclipseLink JAXB(MOXy)都支持相同的扩展。
答案 4 :(得分:0)
每个解决方案都需要复杂的覆盖或注释,这似乎不适用于最新版本。我使用了一种更简单的方法,只需替换烦人的命名空间即可。我希望 Google & Co 使用 JSON 并摆脱 XML。
kml.marshal(file);
String kmlContent = FileUtils.readFileToString(file, "UTF-8");
kmlContent = kmlContent.replaceAll("ns2:","").replace("<kml xmlns:ns2=\"http://www.opengis.net/kml/2.2\" xmlns:ns3=\"http://www.w3.org/2005/Atom\" xmlns:ns4=\"urn:oasis:names:tc:ciq:xsdschema:xAL:2.0\" xmlns:ns5=\"http://www.google.com/kml/ext/2.2\">", "<kml>");
FileUtils.write(file, kmlContent, "UTF-8");
答案 5 :(得分:-2)
我通过设置属性获得了工作结果:
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "");