2013-06-17 2 views
15

Я новичок в JAXB и хотел бы знать, есть ли способ, с помощью которого я могу развязать XML к моему объекту ответа, но используя выражения xpath. Проблема в том, что я звоню в сторонний веб-сервис, и ответ, который я получаю, содержит много деталей. Я не хочу сопоставлять все детали в XML с моим объектом ответа. Я просто хочу отобразить несколько деталей из xml, используя которые я могу получить с помощью определенных выражений XPath и сопоставить их с моим объектом ответа. Есть ли аннотация, которая может помочь мне в этом?Unmarshalling XML с использованием выражения Xpath и jaxb

Для примера рассмотрит следующий ответ

<root> 
    <record> 
    <id>1</id> 
    <name>Ian</name> 
    <AddressDetails> 
     <street> M G Road </street> 
    </AddressDetails> 
    </record> 
</root> 

Я заинтересую только в получении названия улицы, так что я хочу использовать выражение XPath, чтобы получить значение улицы, используя «корневую/запись/AddressDetails/улицы» и карту это на мой объект ответа

public class Response{ 
    // How do i map this in jaxb, I do not wish to map record,id or name elements 
    String street; 

    //getter and setters 
    .... 
} 

Благодаря

+0

, что вы сделали до сих пор? –

+1

Из того, что я нашел, мне кажется, что мне нужно использовать eclipseLink MOXy для достижения этого –

ответ

17

Примечание: Я EclipseLink JAXB (MOXy) свинца и член группы экспертов JAXB (JST-222).

Вы можете использовать удлинитель MOXy @XmlPath для этого прецедента.

Response

import javax.xml.bind.annotation.*; 
import org.eclipse.persistence.oxm.annotations.XmlPath; 

@XmlRootElement(name="root") 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Response{ 
    @XmlPath("record/AddressDetails/street/text()") 
    String street; 

    //getter and setters 
} 

JAXB.свойства

Чтобы использовать Moxy в качестве поставщика JAXB вам необходимо включить файл с именем jaxb.properties в том же пакете модели домена с помощью следующей записи (см http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html)

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

Demo

import java.io.File; 
import javax.xml.bind.*; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Response.class); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     File xml = new File("src/forum17141154/input.xml"); 
     Response response = (Response) unmarshaller.unmarshal(xml); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(response, System.out); 
    } 

} 

Выход

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <record> 
     <AddressDetails> 
     <street> M G Road </street> 
     </AddressDetails> 
    </record> 
</root> 

Для получения более подробной информации

+0

blaise, мне нравится использование @XmlPath. есть ли JSR-аннотация, которая делает подобное, но не бинирует меня на org.eclipse. Спасибо –

+0

'MOXy' дает 404 :( –

10

Если все, что вы хотите это название улицы, просто использовать выражение XPath, чтобы получить его в виде строки, и е или о JAXB - сложный механизм JAXB не добавляет никакой ценности.

import javax.xml.xpath.*; 
import org.xml.sax.InputSource; 

public class XPathDemo { 

    public static void main(String[] args) throws Exception { 
     XPathFactory xpf = XPathFactory.newInstance(); 
     XPath xpath = xpf.newXPath(); 

     InputSource xml = new InputSource("src/forum17141154/input.xml"); 
     String result = (String) xpath.evaluate("/root/record/AddressDetails/street", xml, XPathConstants.STRING); 
     System.out.println(result); 
    } 

} 
+0

@Blaise Я получаю java.net.MalformedURLException: нет протокола: ошибка, когда я пытаюсь использовать вышеприведенный код. Только выше кода с указанным выше xml. – user2771655

+0

Спецификация для «new InputSource()» говорит, что поставляемый SystemId должен быть абсолютным URI, а не относительным URI, как указано в этом примере. –

0

Если вы хотите отобразить в середине документа XML вы можете сделать следующее:

Демо-код

Вы можете использовать анализатор StAX, чтобы перейти к той части документа, которую хотите развязать, и затем отмонтировать XMLStreamReader.

import javax.xml.bind.*; 
import javax.xml.stream.*; 
import javax.xml.transform.stream.StreamSource; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Response.class); 

     XMLInputFactory xif = XMLInputFactory.newFactory(); 
     StreamSource xml = new StreamSource("src/forum17141154/input.xml"); 
     XMLStreamReader xsr = xif.createXMLStreamReader(xml); 
     while(!(xsr.isStartElement() && xsr.getLocalName().equals("AddressDetails"))) { 
      xsr.next(); 
     } 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     JAXBElement<Response> response = unmarshaller.unmarshal(xsr, Response.class); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(response, System.out); 
    } 

} 

Response

сопоставления на объекте домена сделаны относительно фрагмента документа XML вы отображающей в.

import javax.xml.bind.annotation.*; 

@XmlAccessorType(XmlAccessType.FIELD) 
public class Response{ 

    String street; 

    //getter and setters 
} 

Выход

<?xml version="1.0" encoding="UTF-8"?> 
<AddressDetails> 
    <street> M G Road </street> 
</AddressDetails> 

Для получения более подробной информации

+0

Требуется ли создать отдельный объект домена jaxb или я могу повторно использовать те, которые были созданы с помощью xjc, из полного xsd (особенно при экстракции большей части полного дерева документов)? – MRalwasser

+0

@ MRalwasser - вы можете использовать те, которые сгенерированы из XML-схемы. –

+0

спасибо, это то, что я сейчас делаю - у вас есть идея, почему мой unmarshaller создает экземпляр желаемой модели, но не отображает в нее какие-либо дочерние элементы ? – MRalwasser

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