2013-07-08 28 views
1

我有一個很深的XML結構,有很多無意義的包裝,我正在映射到一個Java類。有幾個不同的文件,其內容和結構稍有不同。因爲我希望能夠將結果類轉換爲易於比較的東西(例如,每個表示都包含一個名稱),所以我想知道是否可以爲@XmlPath指定通配符。使用通配符和@XmlPath來解析類似的表示

繼承是我的第一個想法(部分)解決問題,但由於在結構頂部有一個不同的包裝元素,我不知道如何解決這個問題。

示例XML結構

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<s:root xsi:schemaLocation="http://www.example.eu/test ResourceSchema.xsd" xmlns:s="http://www.example.eu/test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <s:resource|s:data|s:container|s:stackoverflow> 
     <s:information> 
      <s:date>2013-07-04</s:date> 
      <s:name>This example does not work</s:name> 
     </s:information> 
     <s:elements> 
      <s:refobj> 
       <s:id>1</s:id> 
       <s:source>First Source</s:source> 
      </s:refobj> 
      <s:refobj> 
       <s:id>2</s:id> 
       <s:source>Second Source</s:source> 
      </s:refobj> 
      <s:refobj> 
       <s:id>5</s:id> 
       <s:source>Fifth Source</s:source> 
      </s:refobj> 
     </s:elements> 
    </s:resource|s:data|s:container|s:stackoverflow> 
</s:root> 

XML中的第二個元素顯然是無效的,儘管這其中的結構不同,並且可以包含相當多的東西。但是,第三層元素information確實存在於每個單一結構中,甚至包含有關在XML內表示哪種類型的元素的信息。

一個快速解決方案是爲每個可能的元素創建一個類,然後嘗試/捕獲所有這些元素直到一個成功,儘管這看起來像一個可怕的解決方案。

什麼是正確的方式來解決這樣的XML相關的問題?我沒有可能改變結構,並且我無法訪問模式來告訴我哪些元素具有多個名稱。

回答

2

MOXy目前不支持@XmlPath中的通配符,但以下方式可以通過StreamReaderDelegate來完成。

域模型

package forum17527941; 

import java.util.Date; 
import javax.xml.bind.annotation.*; 
import org.eclipse.persistence.oxm.annotations.*; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Root { 

    @XmlPath("s:stackoverflow/s:information/s:date/text()") 
    @XmlSchemaType(name="date") 
    private Date date = new Date(); 

    @XmlPath("s:stackoverflow/s:information/s:name/text()") 
    private String name; 

} 

包信息

@XmlSchema(
    namespace="http://www.example.eu/test", 
    xmlns={ 
     @XmlNs(prefix="s", namespaceURI="http://www.example.eu/test") 
    }, 
    elementFormDefault=XmlNsForm.QUALIFIED) 
package forum17527941; 

import javax.xml.bind.annotation.*; 

DEMO CODE

演示

package forum17527941; 

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

public class Demo { 

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

     XMLInputFactory xif = XMLInputFactory.newFactory(); 
     StreamSource xml = new StreamSource("src/forum17527941/input.xml"); 
     XMLStreamReader xsr = xif.createXMLStreamReader(xml); 
     xsr = new StreamReaderDelegate(xsr) { 

      @Override 
      public String getLocalName() { 
       String localName = super.getLocalName(); 
       if("resource".equals(localName) || "data".equals(localName) || "container".equals(localName)) { 
        return "stackoverflow"; 
       } 
       return localName; 
      } 
     }; 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     Root root = (Root) unmarshaller.unmarshal(xsr); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.example.eu/test ResourceSchema.xsd"); 
     marshaller.marshal(root, System.out); 
    } 

} 

input.xml中

用下面的輸入StreamReaderDelegate將導致要報告的resource元素作爲stackoverflow相匹配是映射。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<s:root xsi:schemaLocation="http://www.example.eu/test ResourceSchema.xsd" xmlns:s="http://www.example.eu/test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <s:resource> 
     <s:information> 
      <s:date>2013-07-04</s:date> 
      <s:name>This example does not work</s:name> 
     </s:information> 
    </s:resource> 
</s:root> 

輸出

輸出將匹配在域模型的映射。

<?xml version="1.0" encoding="UTF-8"?> 
<s:root xsi:schemaLocation="http://www.example.eu/test ResourceSchema.xsd" xmlns:s="http://www.example.eu/test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <s:stackoverflow> 
     <s:information> 
     <s:date>2013-07-04</s:date> 
     <s:name>This example does not work</s:name> 
     </s:information> 
    </s:stackoverflow> 
</s:root> 

瞭解更多信息