web-dev-qa-db-ja.com

文字列にマーシャリングするときにJAXBが使用する名前空間プレフィックスをカスタマイズすることは可能ですか?

たとえば、別のスキーマをインポートする単純なスキーマがあります。 2番目のスキーマ(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"、つまり、名前空間に指定されたnameに基づいて解析されます。 has彼らのソフトウェアが機能するための「サードパーティ」であること。

結果の文字列で検索と置換を行う以外に、これを回避する方法を誰かが知っていますか?おそらくカスタムバインディングルールですか?

25
user197614

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

これはその方法を示しています。

別: http://www.systemmobile.com/?p=28

リンクが停止した場合のキービット:

namespacePrefixMapperクラス。com.Sun.xml.bind.marshallerパッケージにあります。抽象クラスには、実装するメソッドが1つあります。

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を実装して、単一のクラスで名前空間のカスタマイズを集中化することもできます。

27
DaveC

私は thatJava SE6でテストしましたが、Java SE 5(説明どおり above ):

    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);

したがって、上記の3番目のプロパティには、Java SE5バージョンと比較して、パッケージ名に追加の.internal.が含まれています。私がまだ見つけていないのは、どの名前空間URIがデフォルトの名前空間( "")になるかをマーシャラーに伝える方法です。 getPreferredPrefix()メソッドをオーバーライドして空の文字列を返すと、Marshallerはデフォルトのネームスペースの属性の書き込みに問題があります(この場合、ns1という新しいネームスペースが作成されます)。

11
basZero

同じ質問がありました。 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)
7
Weslor

これを行う方法があり、これはNamespacePrefixMapperと呼ばれる内部JAXB実装クラスを使用します。 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実装クラスであるため、将来のバージョンで存在する保証はありません。

0
skaffman