29

例如,我有一个导入另一个模式的简单模式。第二个模式 (urn:just:attributes, just-attributes.xsd) 只是定义了一个属性组。

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.example.org/MySchema"
    xmlns:tns="http://www.example.org/MySchema" 
    elementFormDefault="qualified"
    xmlns:ja="urn:just:attributes">

    <import schemaLocation="just-attributes.xsd" namespace="urn:just:attributes"/>

    <element name="MyElement">
        <complexType>
            <attributeGroup ref="ja:AttributeGroup"/>
        </complexType>
    </element>
</schema>

我正在使用 Metro xjc Ant 任务从这个模式中生成类。我遇到的问题是我正在与之交互的第三方应用程序对于命名空间来说是特殊的。这种情况下我需要一个字符串值,所以我必须对其进行序列化。我为此使用样板代码。

private static <T> String marshal(T object) throws JAXBException{
    OutputStream outputStream = new ByteArrayOutputStream();
    JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
    Marshaller marshaller = jaxbContext.createMarshaller();
    marshaller.marshal(object, outputStream);
    return outputStream.toString();
}

这给了我一些类似的东西

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:MyElement xmlns:ns1="urn:just:attributes" xmlns:ns2="http://www.example.org/MySchema" ns1:attrib1="1234" ns1:attrib2="5678"/>

我遇到的问题是这个第三方期望类似的东西xmlns:thirdpartyns="urn:just:attributes",也就是说,它们是根据命名空间的名称进行解析的。他们的软件必须是“第三方”才能工作。

有没有人知道解决这个问题的方法,没有在结果字符串中进行查找和替换?也许是自定义绑定规则?

4

4 回答 4

28

http://hwellmann.blogspot.com/2011/03/jaxb-marshalling-with-custom-namespace.html

这显示了如何做到这一点。

另一个: http ://www.systemmobile.com/?p=280

万一该链接也死掉的关键位:

NamespacePrefixMapper 类,位于 com.sun.xml.bind.marshaller 包中。抽象类有一种方法可以实现:

public abstract String getPreferredPrefix(  
     String namespaceUri,         
     String suggestion,         
     boolean requirePrefix); 

然后

Marshaller marshaller =        
    jaxbContext.createMarshaller();        
marshaller.setProperty(”com.sun.xml.bind.namespacePrefixMapper”,        
    new MyNamespacePrefixMapper());  

如果您还使用 javax.xml.xpath.XPath,您的 NamespacePrefixMapper 也可以实现 javax.xml.namespace.NamespaceContext,将您的命名空间定制集中在一个类中。

于 2009-12-30T23:55:29.533 回答
12

我在Java SE6中进行了测试,与 Java SE 5 的解决方案(如上所述)相比,它需要一个小的改动:

    Marshaller m = context.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
    m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
    m.setProperty("com.sun.xml.internal.bind.namespacePrefixMapper", mapper);

.internal.因此,与 Java SE5 版本相比,上面的第三个属性包含包名称中的附加内容。我还没有发现如何告诉 Marshaller 哪个名称空间 URI 成为默认名称空间 ("")。如果我重写 getPreferredPrefix() 方法并返回一个空字符串,则 Marshaller 会在写入默认命名空间的属性时遇到问题(在这种情况下,它会创建一个名为 ns1 的新命名空间)

于 2011-01-11T13:25:47.557 回答
11

我有同样的问题。在package-info.java(如果你没有它,你可以手动创建它)添加xmlns部分:

@javax.xml.bind.annotation.XmlSchema(xmlns = {
        @javax.xml.bind.annotation.XmlNs(namespaceURI = "urn:just:attributes", prefix = "thirdpartyns") }, 
        elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
于 2015-10-26T10:41:06.183 回答
0

有一种方法可以做到这一点,它使用一个名为NamespacePrefixMapper. 在 JAXB RI 中,它位于 . com.sun.xml.bind.marshaller,但在 Java6 中,它位于com.sun.xml.internal.bind.marshaller.

这是一个抽象类,您可以将其子类化并实现将命名空间 URI 映射到前缀的抽象方法。

然后将该子类的实例注入编组器:

JAXBContext context = ...
Marshaller marshaller = context.createMarshaller();
NamespacePrefixMapper prefixMapper = new MyPrefixMapperImpl();
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", prefixMapper);

Java6 版本的属性名称将有所不同,但您明白了。

请注意,这是一个内部 JAXB 实现类,因此不能保证它会在未来的版本中出现。

于 2009-12-31T00:18:55.900 回答