Java JAXB:如何避免xmlns:xsi的重复命名空间定义
我有一个JAXB设置,其中我使用@XmlJavaTypeAdapter将Java JAXB:如何避免xmlns:xsi的重复命名空间定义,java,xml,jaxb,Java,Xml,Jaxb,我有一个JAXB设置,其中我使用@XmlJavaTypeAdapter将Person类型的对象替换为只包含Person的UUID的PersonRef类型的对象。这个很好用。但是,生成的XML重新声明了相同的名称空间(xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance“)每次使用时。虽然这通常是好的,但感觉不太对劲 如何配置JAXB以在文档一开始就声明xmlns:xsi?我可以手动将名称空间声明添加到根元素吗 下面是我想要实现的一个例子: 当前
Person
类型的对象替换为只包含Person的UUID的PersonRef
类型的对象。这个很好用。但是,生成的XML重新声明了相同的名称空间(xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance“
)每次使用时。虽然这通常是好的,但感觉不太对劲
如何配置JAXB以在文档一开始就声明xmlns:xsi?我可以手动将名称空间声明添加到根元素吗
下面是我想要实现的一个例子:
当前:
<person uuid="6ec0cf24-e880-431b-ada0-a5835e2a565a">
<relation type="CHILD">
<to xsi:type="personRef" uuid="56a930c0-5499-467f-8263-c2a9f9ecc5a0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</relation>
<relation type="CHILD">
<to xsi:type="personRef" uuid="6ec0cf24-e880-431b-ada0-a5835e2a565a" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</relation>
<!-- SNIP: some more relations -->
</person>
<person uuid="6ec0cf24-e880-431b-ada0-a5835e2a565a" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<relation type="CHILD">
<to xsi:type="personRef" uuid="56a930c0-5499-467f-8263-c2a9f9ecc5a0"/>
</relation>
<relation type="CHILD">
<to xsi:type="personRef" uuid="6ec0cf24-e880-431b-ada0-a5835e2a565a"/>
</relation>
<!-- SNIP: some more relations -->
</person>
通缉令:
<person uuid="6ec0cf24-e880-431b-ada0-a5835e2a565a">
<relation type="CHILD">
<to xsi:type="personRef" uuid="56a930c0-5499-467f-8263-c2a9f9ecc5a0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</relation>
<relation type="CHILD">
<to xsi:type="personRef" uuid="6ec0cf24-e880-431b-ada0-a5835e2a565a" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</relation>
<!-- SNIP: some more relations -->
</person>
<person uuid="6ec0cf24-e880-431b-ada0-a5835e2a565a" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<relation type="CHILD">
<to xsi:type="personRef" uuid="56a930c0-5499-467f-8263-c2a9f9ecc5a0"/>
</relation>
<relation type="CHILD">
<to xsi:type="personRef" uuid="6ec0cf24-e880-431b-ada0-a5835e2a565a"/>
</relation>
<!-- SNIP: some more relations -->
</person>
它是XML,因此您可以使用DOM或XSLT处理输出以摆脱多个命名空间引用。它是XML,因此您可以使用DOM或XSLT处理输出以摆脱多个命名空间引用。它看起来像一个 当您使用JAXB 1.0整理XML文档时,Marshaller对象(控制编组过程的JAXB对象)在生成的XML文档中提供名称空间声明。有时,封送拆收器会生成许多看起来冗余的命名空间声明,例如: 避免命名空间重复的配置示例:
JAXBSample
程序完成的第二次编组使用NamespacePrefixMapper
类,如下所示:
@javax.xml.bind.annotation.XmlSchema(
namespace = "mylovelynamespace1",
xmlns = {
@javax.xml.bind.annotation.XmlNs(prefix = "myns1", namespaceURI = "mylovelynamespace1"),
@javax.xml.bind.annotation.XmlNs(prefix = "myns2", namespaceURI = "mylovelynamespace2")
},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.mylovelycompanyname.package;
PreferredMapper
类中的getPreferredPrefix()
方法返回首选前缀,在本例中,mappedNamespacea
将在封送XML的根元素处声明
真的
它看起来像一个
当您使用JAXB 1.0整理XML文档时,Marshaller对象(控制编组过程的JAXB对象)在生成的XML文档中提供名称空间声明。有时,封送拆收器会生成许多看起来冗余的命名空间声明,例如:
避免命名空间重复的配置示例:
JAXBSample
程序完成的第二次编组使用NamespacePrefixMapper
类,如下所示:
@javax.xml.bind.annotation.XmlSchema(
namespace = "mylovelynamespace1",
xmlns = {
@javax.xml.bind.annotation.XmlNs(prefix = "myns1", namespaceURI = "mylovelynamespace1"),
@javax.xml.bind.annotation.XmlNs(prefix = "myns2", namespaceURI = "mylovelynamespace2")
},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.mylovelycompanyname.package;
PreferredMapper
类中的getPreferredPrefix()
方法返回首选前缀,在本例中,mappedNamespacea
将在封送XML的根元素处声明
真的
没有那么漂亮,但是您可以向根元素添加一个空schemaLocation:
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "");
不是很漂亮,但是您可以向根元素添加一个空schemaLocation:
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "");
您可以使用以下代码执行此操作:
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapper() {
@Override
public String[] getPreDeclaredNamespaceUris() {
return new String[] {
XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI
};
}
@Override
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
if (namespaceUri.equals(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI))
return "xsi";
if (namespaceUri.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI))
return "xs";
if (namespaceUri.equals(WellKnownNamespace.XML_MIME_URI))
return "xmime";
return suggestion;
}
});
您可以使用以下代码执行此操作:
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapper() {
@Override
public String[] getPreDeclaredNamespaceUris() {
return new String[] {
XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI
};
}
@Override
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
if (namespaceUri.equals(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI))
return "xsi";
if (namespaceUri.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI))
return "xs";
if (namespaceUri.equals(WellKnownNamespace.XML_MIME_URI))
return "xmime";
return suggestion;
}
});
如果您使用的是Maven,则只需将以下内容添加到pom中:
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
如果您使用的是Maven,则只需将以下内容添加到pom中:
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
这是我在网上找到的最好的答案 创建
xsi:type
声明很可能是因为JAXBElement
声明的类型与值的类型不匹配
如果ObjectFactory
具有正确的JAXBElement
的创建方法,则应使用该方法,因为它应正确填充QName
和类型信息;否则,我将尝试将JAXBElement
的声明类型(第二个构造函数arg)设置为String.class
(假设这是commentTest
)而不是CommentType.Comment
资料来源:
所有者:
这是我在网上找到的最好的答案 创建
xsi:type
声明很可能是因为JAXBElement
声明的类型与值的类型不匹配
如果ObjectFactory
具有正确的JAXBElement
的创建方法,则应使用该方法,因为它应正确填充QName
和类型信息;否则,我将尝试将JAXBElement
的声明类型(第二个构造函数arg)设置为String.class
(假设这是commentTest
)而不是CommentType.Comment
资料来源:
所有者:
cbrettin您只能让名称空间写入一次。您将需要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”):
您只能编写一次名称空间。您将需要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”):
通过执行以下操作添加您的
nsPrefix
映射:
marshaller.setNamespaceMapping(“myns”、“urn:foo”)代码>通过执行以下操作添加您的nsPrefix
映射:
marshaller.setNamespaceMapping(“myns”、“urn:foo”)代码>对不起,我宁愿开枪打自己的脚:)但说真的,在这个任务中使用XSLT或DOM似乎有点过激。最终,这归结为满足我对美学的渴望:)JAXB不是那么可配置的。我认为这是做这件事(或者让它做)的唯一方法。对不起,但我宁愿打自己的脚:)但说真的,在这个任务中使用XSLT或DOM似乎有点过激。最终,这归结为满足我对美学的渴望:)JAXB不是那么可配置的。我认为这是做这件事的唯一方法(或者让它去做)。另请看一个与此无关的问题。谢谢你的回答。默认名称空间PrefixMapper已将“”映射到“xsi”(请参阅)。所以我不认为有一种方法可以更早地使用NamespacePrefixMapper声明名称空间。不过名称空间上下文看起来很有希望。我还是