2016-12-13 3 views
0

Я пытаюсь преобразовать XML в мой Java классКак JAXB может объединить вложенные XML-элементы в строку?

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement(name = "Request") 
public class Request { 

@XmlElement(name="UserName") 
private String username; 

@XmlElement(name="Password") 
private String password; 

@XmlElement(name="XMLPost") 
private String xmlPost; 

public String getUsername() { 
    return username; 
} 

public void setUsername(String username) { 
    this.username = username; 
} 

public String getPassword() { 
    return password; 
} 

public void setPassword(String password) { 
    this.password = password; 
} 

public String getXmlPost() { 
    return xmlPost; 
} 

public void setXmlPost(String xmlPost) { 
    this.xmlPost = xmlPost; 
}} 

Вот мой контекст

JAXBContext jc = JAXVContext.newInstance(Request.class, Report.class, Status.class); 
StringReader reader = new StringReader(xml); 
Unmarshaller unmarshaller = jc.createUnmarshaller(); 

А вот как я использую их вместе

Request request = unmarshaller.unmarshal(reader); 

В Request классе xmlPost будет содержать либо xml Report, либо xml Status Так что я хотел бы захватить его как чтобы я мог попытаться развязать каждый случай.

Класс Report относится к третьей стороне, и у меня нет контроля. Однако, когда я пытаюсь развязать Request, если есть какой-либо XML-файл в поле XMLPost, он также пытается его размонтировать, хотя я указал, что он должен быть просто String. Почему я не могу поместить xml в XMLPost в String?

Благодарим за помощь в продвижении.

+0

Можете ли вы отправить сообщение об ошибке вы получаете? – Adam

+0

@AdamRosini Я не получаю сообщение об ошибке, его просто в том, что в моем классе Request XMLPost является пустой строкой, тогда как я ожидаю, что строка внутри xml внутри нее – Dagron

ответ

1

Вы не можете сделать это напрямую, потому что оно не соответствует спецификации XML. При определении:

@XmlElement(name="XMLPost") 
private String xmlPost; 

это означает, что JAXB в соответствии со спецификацией XML ожидает XML с простым типом элемента XMLPost как хв: строки. а не как другой элемент XML. Чтобы иметь значение в нем ваш запрос должен выглядеть следующим образом:

<Request> 
    <XMLPost>some string in it</XMLPost> 
</Request> 

Так что, если вы хотите иметь другой XML в виде строки, вы должны иметь его либо в XML спасся форме, как:

<Request> 
    <XMLPost>&lt;Report&gt; ...xml escaped content... &lt;/Report&gt;</XMLPost> 
</Request> 

или как CDATA элемент.

<Request> 
    <XMLPost><![CDATA[<Report> ...xml content... </Report>]]></XMLPost> 
</Request> 

Из других рук вы можете иметь два поля как ваши сложные элементы XML

@XmlElement(name="Report") 
private Report report; 

@XmlElement(name="Status") 
private Status status; 

В этом случае вы должны иметь классы JAXB для отчета и статус Тогда, если ваш запрос отчета элемент затем это поле будет иметь значение или когда запрос имеет статус, тогда в поле состояния будет поле, а поле отчета будет равно null.

Возможно, это более подходящий подход, если вам нужен ваш отчет и статус, не беря строку и не распараллеливая их отдельно. Это зависит от вас и того, что вам нужно сделать с этими элементами ...

С точки зрения XML-схемы, что вы сделали:

<xs:element name="Request"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element name="XMLPost" type="xs:string"> 
    </xs:sequence> 
    </xs:complexType>  
</xs:element> 

для второго подхода он будет выглядеть как:

<xs:element name="Request"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element name="Report" minOccurs="0"> 
       <xs:complexType> 
        <xs:sequence> 
         <!-- ... Report type definition ... --> 
        </xs:sequence> 
       </xs:complexType> 
      </xs:element> 
      <xs:element name="Status" minOccurs="0"> 
       <xs:complexType> 
        <xs:sequence> 
         <!-- ... Status type definition ... --> 
        </xs:sequence> 
       </xs:complexType> 
      </xs:element> 
     </xs:sequence> 
    </xs:complexType> 
</xs:element> 

И, наконец, если вам нужно только одно поле, чтобы сохранить либо отчет или состояние объект (не String) определяет его как Объект

@XmlElement(name="XMLPost") 
private Object xmlPost; 

Это соответствует XSD:

<element name="XMLPost" type="xs:anyType" /> 

Конечно, когда вы обработать ваш запрос это до вас, чтобы проверить, что это класс xmlPost объекта

1

Что бы я действительно сделать, это создать XMLPost объект, с дополнительными report и status полей. Затем, после разборки, вы можете увидеть, какой из них заселен.

Однако, чтобы ответить на ваш первоначальный вопрос, вы должны использовать XmlAdapter (In JAXB, how to use @XmlJavaTypeAdapters annotation?). Вот пример того, что адаптер может выглядеть следующим образом:

public class XmlPostStringAdapter extends XmlAdapter<XMLPost, String> { 

    @Override 
    public String unmarshal(XMLPost xmlPost) throws Exception { 
    StringWriter sw = new StringWriter(); 
    JAXBContext jaxbContext = JAXBContext.newInstance(XmlPost.class); 
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); 

    jaxbMarshaller.marshal(xmlPost, sw); 
    return sw.toString(); 
    } 

    @Override 
    public XMLPost marshal(String xmlPost) throws Exception { 
    JAXBContext jaxbContext = JAXBContext.newInstance(XMLPost.class); 
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 
    return (XMLPost) jaxbUnmarshaller.unmarshal(new StringReader(xmlPost)); 
    } 

}

Смежные вопросы