2011-07-05 10 views
9

Im pracuje nad projektem java gdzie muszę przeczytać kilka obiektów z pliku XML, zrobić kilka przetwarzania który zmieni object's ATUTY a następnie napisać obiekt do innego pliku XML. W tym celu używam JAXB z rozrządowych i unmarshalling możliwości, każdy z nich w sposób, jak to:JAXB XML obiektu rozrządowych bez nazw poprzedza

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

} 

Problemem jest to, że automatycznie generowane prefiksy przestrzeni nazw, takich jak NS2 lub NS3 Ciągle pojawiające się w plik wyjściowy, a następnie, kiedy chcemy wykorzystać ten plików z metodą unmarshallXMLFile (będę używał plików wyjściowych jak wejście ponownie później) to przyzwyczajenie sprawdzane przed schematu, i rzuca org.xml.sax.SAXParseException. Tutaj są pliki napisałem:

XML Schema: 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> 

plik wejściowy:

<?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> 

pliku wyjściowego (bez jakiegokolwiek przetwarzania w ogóle: po prostu unmarshalling i zestawiania z powrotem z metodami wspomniany wcześniej)

<?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> 

wyjątek (przy ponownym użyciu pliku ouput s wejście):

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 

Ive czytam na ten temat i spróbował mnóstwo powiązanych odpowiedzi, ale żaden z nich nie wydaje się usunąć prefiksy. Poszedłem koryta tej guide ale wersja JAXB używam nie obsługuje NamespacePrefixMapper. Próbowałem za pomocą adnotacji, jak opisano here skonfigurowanie prefiksy ale nie działała.

Być może istnieje sposób na pozbycie się przedrostków przestrzeni nazw: wszystkie fora, odpowiedzi i dyskusje, o których mówiłem, mówią o dostosowywaniu tych prefiksów, po prostu chcę się ich pozbyć. Ale jakoś to sprawia, że ​​myślę, że brakuje mi czegoś zarówno w moim pliku wejściowym, jak i schemacie. Czy są dobrze napisane? Powiedziałbym, że tam jest problem, ponieważ jest to pierwszy raz pracować z XML i XSD na tej głębokości, a co Ive zrobić opiera się wyłącznie na tym, co Ive znaleźć w Internecie. Wszelkie wskazówki dotyczące ulepszania projektów xml i xsd byłyby wysoko cenione. Czy powinienem używać jakichś prefiksów w pliku wejściowym lub schemacie, aby struktura JAXB nie generowała losowych prefiksów w czasie zestawiania?

z góry dzięki, mam nadzieję, że chłopaki mogą mi pomóc.

-

Dziękuję bardzo za odpowiedź. W ten sposób mogę użyć NamespacePrefixMapper. Jednak, kiedy go używać, mój kod utrzymuje rzucanie wyjątki gdy uruchamiam go:

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) 

Uważam, że musi coś zrobić z plikiem .properties: Nie używam czegoś takiego, i przystań zmienił niczego .

+0

podobny temat/możliwy duplikat: http://stackoverflow.com/questions/1982977/is-it-possible-to-custo mize-the-namespace-prefix-that-jaxb-uses-when-marshalling –

Odpowiedz

3

Cóż, po kilku badań, próbowałem za pomocą znacznika @XMLElement na każdym atrybucie klas Próbuję serializacji, określając wyraźnie, co było moim nazw i używając ten sam na każdym atrybucie:

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

Udało się bezbłędnie: nie więcej dziwne przestrzenie nazw w rozesłanym pliku.

Chcę podziękować za odpowiedź: próbowałem również, ale mam wyjątek związany z dziwnym pakietem językowym. Cieszę się, że to prostsze podejście rozwiązało problem.

+0

możemy użyć przedrostka w tym @XmlElement –

3

Spróbuj za pomocą NamespacePrefixMapper:

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

Dziękuję bardzo za odpowiedź. W ten sposób mogę użyć NamespacePrefixMapper. Jednak gdy go używam, mój kod generuje wyjątki podczas uruchamiania: – Lak

11

Zamiast określać atrybut przestrzeni nazw @XmlElement w każdym elemencie, łatwiej jest opisywać na poziomie pakietu. Robisz to, tworząc plik package-info.java tuż pod paczką, którą chcesz opatrzyć adnotacją.

Na przykład, jeśli chcesz opisywanie pakiet org.example, następnie plik o nazwie package-info.java muszą być umieszczone w katalogu org/przykład o następującej treści:

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

Ważne jest, aby pamiętać, że trzeba opisywać każdy pakiet, który zawiera klasy, które twój plan przekazuje lub są przez nie przywoływane.

Nadzieja to pomaga :)

1

Java 7/8 rozwiązanie

Ten problem jest związany z domyślnym dostawcą implementacji JAXB. Znalazłem rozwiązanie wykorzystujące inną implementację: EclipseLink MOXy.

1. dodać zależność w pom.xml
<dependency> 
    <groupId>org.eclipse.persistence</groupId> 
    <artifactId>org.eclipse.persistence.moxy</artifactId> 
    <version>2.5.0</version> 
</dependency>` 
2. Utwórz jaxb.properties pliku zawierającego następującą linię
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

przenieść plik do modelu pakietu

3. Utwórz plik pakietu. java w pakiet modelu
@XmlSchema(xmlns = { @XmlNs(prefix = "video", namespaceURI = "http://www.google.com/schemas/sitemap-video/1.1"), 
     @XmlNs(prefix = "", namespaceURI = "http://www.sitemaps.org/schemas/sitemap/0.9")}) 

package it.my.sitemap.model; 

import javax.xml.bind.annotation.XmlNs; 
import javax.xml.bind.annotation.XmlSchema;