web-dev-qa-db-ja.com

名前空間プレフィックスなしのJAXBXMLオブジェクトマーシャリング

XMLファイルからいくつかのオブジェクトを読み取る必要があるJavaプロジェクトで作業しています。オブジェクトの属性を変更する処理を実行してから、オブジェクトを別のXMLファイルに書き込みます。そのために目的は、マーシャリング機能とアンマーシャリング機能を備えたJAXBを使用しており、それぞれを次のようなメソッドで使用しています。

private MyObject unmarshallXMLFile(String file) {
    MyObject t=null;
    try {
        jc = JAXBContext.newInstance("foo.bar");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        SchemaFactory sf = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
        unmarshaller.setSchema(sf.newSchema(new File("MySchema.xsd")));
        t = (Task) unmarshaller.unmarshal(new File(file));
    } catch (JAXBException e) {
        e.printStackTrace();
    } catch (SAXException e) {
        e.printStackTrace();
    }
    return t;
}

private void marshallXMLFile(String file) {
    task.setReplay(Boolean.TRUE);
    Marshaller marshaller;
    try {
        marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, new Boolean(true));
        marshaller.marshal(task, new FileOutputStream(file));
    } catch (JAXBException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

}

問題は、ns2やns3などの自動生成された名前空間プレフィックスが出力ファイルに表示され続けることです。このファイルをunmarshallXMLFileメソッドで再利用する場合(後で再び入力として出力ファイルを使用します)、取得されません。スキーマに対して検証され、org.xml.sax.SAXParseExceptionをスローします。これが私が書いたファイルです:

XMLスキーマ:MySchema.xsd

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/MySchema"
    xmlns:spm="http://www.example.org/MySchema"
    elementFormDefault="qualified"
    attributeFormDefault="qualified">

    <element name="task" >
        <complexType>
            <sequence>
                <element name="replay" type="boolean" default="false"/>
                <element name="threads" type="spm:spThread" maxOccurs="unbounded" minOccurs="1" />
            </sequence>
        </complexType>
    </element>

    <complexType name="spThread">
        <sequence>
            <element name="SPThreadID" type="int" />
            <element name="durtime" minOccurs="0" default="0">
                <simpleType>
                    <restriction base="int">
                        <minInclusive value="0" />
                    </restriction>
                </simpleType>
            </element>
            <element name="minexecutions" minOccurs="0" default="0">
                <simpleType>
                    <restriction base="int">
                        <minInclusive value="0" />
                    </restriction>
                </simpleType>
            </element>
            <element name="numThreads" type="int" />
            <element name="procedures" type="spm:procedure" minOccurs="1"
                maxOccurs="unbounded" />
        </sequence>
    </complexType>

    <complexType name="procedure">
        <sequence>
            <element name="id" type="int" minOccurs="1" />
            <element name="name" type="string" minOccurs="1" />
            <element name="weight" minOccurs="1">
                <simpleType>
                    <restriction base="int">
                        <minInclusive value="0" />
                        <maxInclusive value="100" />
                    </restriction>
                </simpleType>
            </element>
            <element name="parameterPool" type="spm:parameter" nillable="true"
                minOccurs="0" maxOccurs="unbounded" />
        </sequence>
    </complexType>

    <complexType name="parameter">
        <sequence>
            <element name="name" type="string" minOccurs="1" />
            <element name="dataType" type="spm:parameterDataType" default="integer"/>
            <element name="parmType" type="spm:parameterType" default="in"
                minOccurs="0" />
            <element name="minValue" type="string"/>
            <element name="maxValue" type="string"/>
            <element name="value" type="string"/>
        </sequence>
    </complexType>

    <simpleType name="parameterDataType">
        <restriction base="string">
            <enumeration value="integer" />
            <enumeration value="varchar" />
            <enumeration value="char" />
        </restriction>
    </simpleType>

    <simpleType name="parameterType">
        <restriction base="string">
            <enumeration value="in" />
            <enumeration value="out" />
            <enumeration value="in_out" />
        </restriction>
    </simpleType>

</schema>

入力ファイル:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<task xmlns="http://www.example.org/MySchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/MySchema MySchema.xsd ">
    <replay>true</replay>
    <threads>
        <SPThreadID>0</SPThreadID>
        <durtime>10</durtime>
        <minexecutions>2</minexecutions>
        <numThreads>3</numThreads>
        <procedures>
            <id>1</id>
            <name>run</name>
            <weight>15</weight>
            <parameterPool>
                <name>energy</name>
                <dataType>integer</dataType>
                <parmType>in</parmType>
                <minValue>10</minValue>
                <maxValue>50</maxValue>
                <value>11</value>                
            </parameterPool>
            <parameterPool>
                <name>speed</name>
                <dataType>integer</dataType>
                <parmType>in</parmType>
                <minValue>12</minValue>
                <maxValue>80</maxValue>
                <value>13</value>                                
            </parameterPool>
        </procedures>
    </threads>
</task>

出力ファイル(何も処理せずに:前述の方法でマーシャリングを解除してマーシャリングします)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:task xmlns="http://www.example.org/MySchema" xmlns:ns2="http://www.example.org/MySchema.xsd">
    <replay>true</replay>
    <threads>
        <SPThreadID>0</SPThreadID>
        <durtime>10</durtime>
        <minexecutions>2</minexecutions>
        <numThreads>3</numThreads>
        <procedures>
            <id>1</id>
            <name>run</name>
            <weight>15</weight>
            <parameterPool>
                <name>energy</name>
                <dataType>integer</dataType>
                <parmType>in</parmType>
                <minValue>10</minValue>
                <maxValue>50</maxValue>
                <value>11</value>
            </parameterPool>
            <parameterPool>
                <name>speed</name>
                <dataType>integer</dataType>
                <parmType>in</parmType>
                <minValue>12</minValue>
                <maxValue>80</maxValue>
                <value>13</value>
            </parameterPool>
        </procedures>
    </threads>
</ns2:task>

例外(出力ファイルを入力として再度使用する場合):

javax.xml.bind.UnmarshalException
 - with linked exception:
[org.xml.sax.SAXParseException: cvc-elt.1: The declaration of the element'ns3:task' could not be found.]
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.Java:326)
    at com.Sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.Java:500)
    at com.Sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.Java:206)
    at com.Sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.Java:175)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.Java:148)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.Java:153)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.Java:162)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.Java:180)
    at Test.main(Test.Java:48)
Caused by: org.xml.sax.SAXParseException: cvc-elt.1: The declaration of the element'ns3:task' could not be found.
    at org.Apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
    at org.Apache.xerces.util.ErrorHandlerWrapper.error(Unknown Source)
    at org.Apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
    at org.Apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
    at org.Apache.xerces.impl.xs.XMLSchemaValidator.handleStartElement(Unknown Source)
    at org.Apache.xerces.impl.xs.XMLSchemaValidator.startElement(Unknown Source)
    at org.Apache.xerces.jaxp.validation.XMLSchemaValidatorHandler.startElement(Unknown Source)
    at com.Sun.xml.internal.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.startElement(ValidatingUnmarshaller.Java:85)
    at com.Sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.Java:113)
    at org.Apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
    at org.Apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
    at org.Apache.xerces.impl.XMLNSDocumentScannerImpl$NSContentDispatcher.scanRootElementHook(Unknown Source)
    at org.Apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
    at org.Apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at org.Apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.Apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.Apache.xerces.parsers.XMLParser.parse(Unknown Source)
    at org.Apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
    at com.Sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.Java:202)
    ... 6 more

私は主題について読んでいて、関連する答えをたくさん試しましたが、それらのどれも接頭辞を削除していないようです。私はこれを通り抜けました ガイド しかし私が使用しているjaxbのバージョンはNamespacePrefixMapperをサポートしていません。説明されているように注釈を使用してみました ここ プレフィックスを設定しましたが、うまくいきませんでした。

たぶん、この名前空間プレフィックスを取り除く方法があります。私が見つけたすべてのフォーラム、回答、およびディスカッションは、このプレフィックスのカスタマイズについて話します。私はそれらを取り除きたいだけです。しかし、どういうわけか、入力ファイルとスキーマの両方に何かが欠けていると思います。それらはよく書かれていますか?この深さでxmlとxsdを操作するのは初めてであり、私が行ったことはオンラインで見つけたものにのみ基づいているため、問題があると言えます。 xmlおよびxsdデザインを改善するためのヒントをいただければ幸いです。

jAXBフレームワークがマーシャリング時にランダムなプレフィックスを生成しないように、入力ファイルまたはスキーマで何らかのプレフィックスを使用する必要がありますか?

よろしくお願いします。皆さんが私を助けてくれることを願っています。

-

回答ありがとうございます。そのようにして、NamespacePrefixMapperを使用できます。ただし、使用すると、実行時にコードが例外をスローし続けます。

Exception in thread "main" Java.util.MissingResourceException: Can't find bundle for base name javax.xml.bind.Messages, locale de_DE
    at Java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.Java:863)
    at Java.util.ResourceBundle.getBundleImpl(ResourceBundle.Java:832)
    at Java.util.ResourceBundle.getBundle(ResourceBundle.Java:576)
    at javax.xml.bind.Messages.format(Messages.Java:47)
    at javax.xml.bind.Messages.format(Messages.Java:36)
    at javax.xml.bind.PropertyException.<init>(PropertyException.Java:99)
    at javax.xml.bind.helpers.AbstractMarshallerImpl.setProperty(AbstractMarshallerImpl.Java:349)
    at com.Sun.xml.internal.bind.v2.runtime.MarshallerImpl.setProperty(MarshallerImpl.Java:527)
    at Test.main(Test.Java:95)

.propertiesファイルで何かをしなければならないことがわかりました。私はそのようなものを使用していません。何も変更していません。

11
Lak

調査の結果、シリアル化しようとしているクラスのすべての属性に@XMLElementタグを使用し、名前空間が何であるかを明確に指定し、すべての属性に同じタグを使用してみました。

@XmlElement(required = true, name="myObjectPool", namespace="http://www.example.org/StoredProceduresSchema")
    protected List<MyObject> myObjectPool;

それは完璧に機能しました。マーシャリングされたファイルに奇妙な名前空間はもうありません。

彼の答えに感謝したい:私もそれを試したが、奇妙な言語バンドル関連の例外が発生した。この単純なアプローチで問題が解決したことをうれしく思います。

3
Lak

すべての要素で@XmlElementの名前空間属性を指定する代わりに、パッケージレベルで注釈を付ける方が簡単です。これを行うには、注釈を付けるパッケージのすぐ下にファイルpackage-info.Javaを作成します。

たとえば、パッケージorg.exampleに注釈を付ける場合は、package-info.Javaという名前のファイルを次の内容のディレクトリorg/example内に配置する必要があります。

@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.example.org/StoredProceduresSchema", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.example;

マーシャリングする予定のクラス、またはそれらによって参照されるクラスを含むすべてのパッケージに注釈を付ける必要があることに注意することが重要です。

お役に立てれば :)

12
Cristian Ebbens

NamespacePrefixMapperを使用してみてください:

NamespacePrefixMapper mapper = new NamespacePrefixMapper() {
    public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
        return "";
    }
};
marshaller.setProperty("com.Sun.xml.bind.namespacePrefixMapper", mapper);
4
kwo

次に、リファレンスとは異なるJAXB実装を使用している可能性があります。この記事を読んで再試行してください: http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html (または怠惰な場合:com.Sun.xmlを置き換えてください.bind.namespacePrefixMapperとcom.Sun.xml.internal.bind.namespacePrefixMapper)

1
Stefan