2017-03-28 5 views
0

メッセージ内の特定の要素でアンマーシャリングを開始するために「startTag」を提供できるXMLメッセージをアンマーシャリングするためのJavaプロシージャを作成しました。この選択を行うにはXMLStreamReaderを使用しました。XmlStreamReaderからのJAXBアンマーシャリングによりnullオブジェクトが返される

私が実行している問題の完全なコピー可能なデモは以下の通りです。 'xml'メッセージは、私が扱う必要があります。残念ながら結果にnullカーオブジェクトが生成されますが、 'xmlStripped'メッセージは完全にアンマーシャリングされた結果になります。

<response>要素のxmlns="http://www.example.com/type"名前空間に問題を切り分けました。これを削除すると、 'xml'が正しくアンマーシャリングされます。

私はXML上でコントロールを持っています。 'xml'変数は私が扱う必要があります。私は少し XSD/ObjectFactoryのコントロールを持っているので、私の最初の行動はアンマーシャルプロシージャの解決策を探すことです。

これがなぜ失敗するのか、解決策があるのか​​分かっている場合は教えてください。ありがとう!

package-info.java

@XmlSchema(namespace="http://www.example.com/type", elementFormDefault=XmlNsForm.QUALIFIED) 

package mypkg; 

import javax.xml.bind.annotation.*; 

これを:あなたはpackage-info.javaを作成し、追加して、モデルののelementFormDefault = "資格"を設定することができます

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBElement; 
import javax.xml.bind.JAXBException; 
import javax.xml.bind.Unmarshaller; 
import javax.xml.bind.annotation.*; 
import javax.xml.namespace.QName; 
import javax.xml.stream.XMLInputFactory; 
import javax.xml.stream.XMLStreamException; 
import javax.xml.stream.XMLStreamReader; 
import java.io.Reader; 
import java.io.StringReader; 

public class XmlStreamReaderUnmarshallingTest { 

    private static JAXBContext jaxbContext; 

    static { 
     try { 
      jaxbContext = JAXBContext.newInstance(ObjectFactory.class); 
     } catch (JAXBException e) { 
      e.printStackTrace(); 
     } 
    } 

    private static String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
      "<soapenv:Envelope xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \n" + 
      "\txmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" \n" + 
      "\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" + 
      "\t<soapenv:Body>\n" + 
      "\t\t<response xmlns=\"http://www.example.com/type\">\n" + 
      "\t\t\t<type:serviceResponse xmlns:type=\"http://www.example.com/type\">\n" + 
      "\t\t\t\t<Body>\n" + 
      "\t\t\t\t\t<Car>\n" + 
      "\t\t\t\t\t\t<Brand>Mitsubishi</Brand>\n" + 
      "\t\t\t\t\t\t<Color>Red</Color>\n" + 
      "\t\t\t\t\t</Car>\n" + 
      "\t\t\t\t</Body>\n" + 
      "\t\t\t</type:serviceResponse>\n" + 
      "\t\t</response>\n" + 
      "\t</soapenv:Body>\n" + 
      "</soapenv:Envelope>"; 


    private static String xmlStripped = "<type:serviceResponse xmlns:type=\"http://www.example.com/type\">\n" + 
      "\t\t\t\t<Body>\n" + 
      "\t\t\t\t\t<Car>\n" + 
      "\t\t\t\t\t\t<Brand>Mitsubishi</Brand>\n" + 
      "\t\t\t\t\t\t<Color>Red</Color>\n" + 
      "\t\t\t\t\t</Car>\n" + 
      "\t\t\t\t</Body>\n" + 
      "\t\t\t</type:serviceResponse>"; 


    public static void main(String[] args) throws JAXBException, XMLStreamException { 
     readXml(xml, "serviceResponse"); 
     readXml(xmlStripped, "serviceResponse"); 
    } 

    private static void readXml(String inputXml, String startFromElement) throws JAXBException, XMLStreamException { 

     final XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory(); 
     final Reader reader = new StringReader(inputXml); 
     final XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(reader); 
     final XMLStreamReader streamReader = skipToElement(xmlStreamReader, startFromElement); 
     final MyServiceResponse serviceResponse = (MyServiceResponse) unmarshal(streamReader); 

     if(serviceResponse.getBody().getCar() == null) { 
      System.out.println("It didn't work :-("); 
     } else { 
      System.out.println("It worked"); 
     } 
    } 

    private static XMLStreamReader skipToElement(final XMLStreamReader xsr, final String startAtElement) throws XMLStreamException { 
     while (startAtElement != null && xsr.hasNext()) { 
      xsr.next(); 
      if (xsr.hasName()) { 
       final String name = xsr.getName().getLocalPart(); 
       if (name.equals(startAtElement)) { 
        return xsr; 
       } 
      } 
     } 

     throw new IllegalArgumentException(String.format("Could not find element %s in response", startAtElement)); 
    } 

    private static Object unmarshal(final XMLStreamReader xsr) throws JAXBException { 
     final Object entity = unmarshaller(jaxbContext).unmarshal(xsr); 
     return (entity instanceof JAXBElement ? ((JAXBElement) entity).getValue() : entity); 
    } 

    // Create unmarshaller every time 
    private static Unmarshaller unmarshaller(JAXBContext context) throws JAXBException { 

     return context.createUnmarshaller(); 

    } 
} 


@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "MyServiceResponse", propOrder = { 

}) 
class MyServiceResponse { 

    @XmlElement(name = "Body") 
    protected MyServiceResponse.Body body; 

    /** 
    * Gets the value of the body property. 
    * 
    * @return 
    *  possible object is 
    *  {@link MyServiceResponse.Body } 
    * 
    */ 
    public MyServiceResponse.Body getBody() { 
     return body; 
    } 

    /** 
    * Sets the value of the body property. 
    * 
    * @param value 
    *  allowed object is 
    *  {@link MyServiceResponse.Body } 
    * 
    */ 
    public void setBody(MyServiceResponse.Body value) { 
     this.body = value; 
    } 


    /** 
    * <p>Java class for anonymous complex type. 
    * 
    * <p>The following schema fragment specifies the expected content contained within this class. 
    * 
    * <pre> 
    * &lt;complexType&gt; 
    * &lt;complexContent&gt; 
    *  &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt; 
    *  &lt;all&gt; 
    *   &lt;element name="Car" minOccurs="0"&gt; 
    *   &lt;complexType&gt; 
    *    &lt;complexContent&gt; 
    *    &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt; 
    *     &lt;all&gt; 
    *     &lt;element name="Brand" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/&gt; 
    *     &lt;element name="Color" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/&gt; 
    *     &lt;/all&gt; 
    *    &lt;/restriction&gt; 
    *    &lt;/complexContent&gt; 
    *   &lt;/complexType&gt; 
    *   &lt;/element&gt; 
    *  &lt;/all&gt; 
    *  &lt;/restriction&gt; 
    * &lt;/complexContent&gt; 
    * &lt;/complexType&gt; 
    * </pre> 
    * 
    * 
    */ 
    @XmlAccessorType(XmlAccessType.FIELD) 
    @XmlType(name = "", propOrder = { 

    }) 
    public static class Body { 

     @XmlElement(name = "Car") 
     protected MyServiceResponse.Body.Car car; 

     /** 
     * Gets the value of the car property. 
     * 
     * @return 
     *  possible object is 
     *  {@link MyServiceResponse.Body.Car } 
     * 
     */ 
     public MyServiceResponse.Body.Car getCar() { 
      return car; 
     } 

     /** 
     * Sets the value of the car property. 
     * 
     * @param value 
     *  allowed object is 
     *  {@link MyServiceResponse.Body.Car } 
     * 
     */ 
     public void setCar(MyServiceResponse.Body.Car value) { 
      this.car = value; 
     } 


     /** 
     * <p>Java class for anonymous complex type. 
     * 
     * <p>The following schema fragment specifies the expected content contained within this class. 
     * 
     * <pre> 
     * &lt;complexType&gt; 
     * &lt;complexContent&gt; 
     *  &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt; 
     *  &lt;all&gt; 
     *   &lt;element name="Brand" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/&gt; 
     *   &lt;element name="Color" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/&gt; 
     *  &lt;/all&gt; 
     *  &lt;/restriction&gt; 
     * &lt;/complexContent&gt; 
     * &lt;/complexType&gt; 
     * </pre> 
     * 
     * 
     */ 
     @XmlAccessorType(XmlAccessType.FIELD) 
     @XmlType(name = "", propOrder = { 

     }) 
     public static class Car { 

      @XmlElement(name = "Brand") 
      protected String brand; 
      @XmlElement(name = "Color") 
      protected String color; 

      /** 
      * Gets the value of the brand property. 
      * 
      * @return 
      *  possible object is 
      *  {@link String } 
      * 
      */ 
      public String getBrand() { 
       return brand; 
      } 

      /** 
      * Sets the value of the brand property. 
      * 
      * @param value 
      *  allowed object is 
      *  {@link String } 
      * 
      */ 
      public void setBrand(String value) { 
       this.brand = value; 
      } 

      /** 
      * Gets the value of the color property. 
      * 
      * @return 
      *  possible object is 
      *  {@link String } 
      * 
      */ 
      public String getColor() { 
       return color; 
      } 

      /** 
      * Sets the value of the color property. 
      * 
      * @param value 
      *  allowed object is 
      *  {@link String } 
      * 
      */ 
      public void setColor(String value) { 
       this.color = value; 
      } 

     } 

    } 

} 


@XmlRegistry 
class ObjectFactory { 

    private final static QName _ServiceResponse_QNAME = new QName("http://www.example.com/type", "serviceResponse"); 

    /** 
    * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.example.type 
    * 
    */ 
    public ObjectFactory() { 
    } 

    /** 
    * Create an instance of {@link MyServiceResponse } 
    * 
    */ 
    public MyServiceResponse createMyServiceResponse() { 
     return new MyServiceResponse(); 
    } 

    /** 
    * Create an instance of {@link MyServiceResponse.Body } 
    * 
    */ 
    public MyServiceResponse.Body createMyServiceResponseBody() { 
     return new MyServiceResponse.Body(); 
    } 

    /** 
    * Create an instance of {@link MyServiceResponse.Body.Car } 
    * 
    */ 
    public MyServiceResponse.Body.Car createMyServiceResponseBodyCar() { 
     return new MyServiceResponse.Body.Car(); 
    } 

    /** 
    * Create an instance of {@link JAXBElement }{@code <}{@link MyServiceResponse }{@code >}} 
    * 
    */ 
    @XmlElementDecl(namespace = "http://www.example.com/type", name = "serviceResponse") 
    public JAXBElement<MyServiceResponse> createServiceResponse(MyServiceResponse value) { 
     return new JAXBElement<MyServiceResponse>(_ServiceResponse_QNAME, MyServiceResponse.class, null, value); 
    } 

} 

答えて

0

あなたの通常のXMLは許可されますが、あなたの "剥奪された" XMLは動作しません。 2つの違いは、外側のラッパー要素の「剥ぎ取り」以外に、元のXMLにはデフォルトの名前空間セットがあり、取り除かれたXMLには含まれていないということです。

+0

ありがとう!これは動作し、私が使用するXSDをできるだけ小さく変更する必要があるため、私にとっては最も適切なソリューションでした。私はelementFormDefault = "qualified"を 'schema'要素に追加し、それはelementFormDefault =" XmlNsForm.QUALIFIED "を含むpackage-info.javaファイルを生成するために使用するmaven-jaxb2-pluginを引き起こします。 – Julius

1

は@XmlType注釈にname属性を設定します。

@XmlType(name = "Body", propOrder = { 

}) 
public static class Body { ... } 

@XmlType(name = "Car", propOrder = { 

}) 
public static class Car { ... } 
+0

ありがとうございます。これも機能しますが、スコットのソリューションは私の状況にとっては少し良いマッチです。 – Julius

関連する問題