2011-03-24 132 views
5

我有一個模式定義元素和屬性的默認值。我正嘗試使用基於該模式的JAXB解析文檔,但JAXB未設置默認值。關於如何讓JAXB兌現模式的默認值的任何想法?JAXB是否支持默認模式值?

example.xsd:

<?xml version="1.0" encoding="UTF-8"?><xs:schemaxmlns:xs="http://www.w3.org/2001/XMLSchema" 
targetNamespace="http://www.example.org/example" 
xmlns:tns="http://www.example.org/example"> 

<xs:element name="root" type="tns:rootType"/> 

<xs:complexType name="rootType"> 
    <xs:sequence> 
     <xs:element name="child" type="tns:childType"/> 
    </xs:sequence> 
</xs:complexType> 

<xs:complexType name="childType"> 
    <xs:sequence> 
     <xs:element name="childVal" type="xs:string" default="defaultElVal"/> 
    </xs:sequence> 
    <xs:attribute name="attr" type="xs:string" default="defaultAttrVal"/> 
</xs:complexType> 

example1.xml

<?xml version="1.0" encoding="UTF-8"?> 
<tns:root xmlns:tns="http://www.example.org/example" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/example example.xsd "> 
    <child> 
    <childVal/> 
    </child> 
</tns:root> 

TestParser.java

package test; 
import java.io.File; 
import javax.xml.XMLConstants; 
import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Unmarshaller; 
import javax.xml.validation.Schema; 
import javax.xml.validation.SchemaFactory; 
public class TestParser {  
    public static void main(String[] pArgs) { 
     try { 
      JAXBContext context = JAXBContext.newInstance(RootElement.class); 
      Unmarshaller unmarshaller = context.createUnmarshaller(); 

      SchemaFactory schemaFac = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
      Schema sysConfigSchema = schemaFac.newSchema(
        new File("example.xsd")); 
      unmarshaller.setSchema(sysConfigSchema); 
      RootElement root = (RootElement)unmarshaller.unmarshal(
        new File("example1.xml")); 
      System.out.println("Child Val: " + root.getChild().getChildVal()); 
      System.out.println("Child Attr: " + root.getChild().getAttr()); 
     } catch (Exception e) { 
      System.out.println(e.getMessage()); 
      e.printStackTrace(); 
     } 
    } 
} 

RootElement.java

package test; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement(name="root", namespace="http://www.example.org/example") 
public class RootElement { 

    private ChildEl child; 

    public RootElement() {} 

    public ChildEl getChild() { 
     return child; 
    } 

    public void setChild(ChildEl pChild) { 
     this.child = pChild; 
    } 
} 

ChildEl.java

package test; 

import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement(name="child") 
public class ChildEl { 

    private String attr; 
    private String childVal; 

    public ChildEl() {}; 

    @XmlAttribute 
    public String getAttr() { 
     return attr; 
    } 
    public void setAttr(String pAttr) { 
     this.attr = pAttr; 
    } 

    public String getChildVal() { 
     return childVal; 
    } 
    public void setChildVal(String pVal) { 
     this.childVal = pVal; 
    } 

} 

回答

9

元素默認值

得到你需要如下注釋它的元素屬性的默認值:

@XmlElement(defaultValue="defaultElVal") 
public String getChildVal() { 
    return childVal; 
} 

屬性默認值

如果您使用EclipseLink JAXB (MOXy),您將使用您提供的代碼獲取默認屬性值。 JAXB的Metro實現中可能存在一個錯誤,使得它無法正常工作。注意我領導MOXy實現。


替代方法

下面的代碼應與任何JAXB實現工作,而無需任何代碼更改模型。你可以做以下和槓桿的SAXSource:

import java.io.File; 
import java.io.FileInputStream; 

import javax.xml.XMLConstants; 
import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Unmarshaller; 
import javax.xml.parsers.SAXParserFactory; 
import javax.xml.transform.sax.SAXSource; 
import javax.xml.validation.Schema; 
import javax.xml.validation.SchemaFactory; 

import org.xml.sax.InputSource; 
import org.xml.sax.XMLReader; 
public class TestParser {  
    public static void main(String[] pArgs) { 
     try { 
      JAXBContext context = JAXBContext.newInstance(RootElement.class); 
      Unmarshaller unmarshaller = context.createUnmarshaller(); 

      SchemaFactory schemaFac = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
      Schema sysConfigSchema = schemaFac.newSchema(
        new File("example.xsd")); 

      SAXParserFactory spf = SAXParserFactory.newInstance(); 
      spf.setNamespaceAware(true); 
      spf.setSchema(sysConfigSchema); 
      XMLReader xmlReader = spf.newSAXParser().getXMLReader(); 
      SAXSource source = new SAXSource(xmlReader, new InputSource(new FileInputStream("example1.xml"))); 
      RootElement root = (RootElement)unmarshaller.unmarshal(
        source); 
      System.out.println("Child Val: " + root.getChild().getChildVal()); 
      System.out.println("Child Attr: " + root.getChild().getAttr()); 
     } catch (Exception e) { 
      System.out.println(e.getMessage()); 
      e.printStackTrace(); 
     } 
    } 
} 
4

我發現你正在試圖做的是明智的,尤其是有屬性與簡單的元素和諧的。這似乎很奇怪,但似乎jaxb2實現者選擇添加一組額外的擴展,您必須添加一組擴展才能獲得所需的行爲。請參閱:

(我會寧願看到屬性和至少簡單類型的元素之間更自然的默認行爲和一致性 - 無需註冊插件然後提供一個插件我的唯一的傢伙爲什麼這樣做沒有完成或向後兼容 - 猜測)

jaxb2-commons默認值插件指的是一個額外的命令(和罐子)你添加到xjc依次添加默認行爲到現場。在我的情況:(其中,當然,有條件的空支票呈現的默認值與否)

public String getScalarOptionalMaxAndDefaultString() { 
    if (scalarOptionalMaxAndDefaultString == null) { 
     return "def val 1"; 
    } else { 
     return scalarOptionalMaxAndDefaultString; 
    } 
} 

使用布萊斯Doughan似乎是實際工作中各地。根據XML文檔的性質,這可能是完美的。

然而,看起來這個默認值插件可能會將解決方案移到構建過程中,而不會看到代碼的變化(假設您使用Dom而不是Sax分析器Blaise建議的)。

它看起來是默認值插件解決問題,並可能提供額外的可擴展性(不需要這種高級自定義),在極少數情況下,您需要更多的程序化默認值控制運行xjc。

這裏是一個Maven配置片斷的情況下,它可以幫助:

<plugin> 
    <groupId>org.jvnet.jaxb2.maven2</groupId> 
    <artifactId>maven-jaxb2-plugin</artifactId> 
    <version>0.8.0</version> 
    <executions> 
     <execution> 
     <phase>generate-sources</phase> 
     <goals> 
      <goal>generate</goal> 
     </goals> 
     <configuration> 
      <args> 
       <arg>-Xdefault-value</arg> 
      </args> 
      <plugins> 
       <plugin> 
        <groupId>org.jvnet.jaxb2_commons</groupId> 
        <artifactId>jaxb2-default-value</artifactId> 
        <version>1.1</version> 
       </plugin> 
      </plugins> 
     </configuration> 
     </execution> 
    </executions> 
    <configuration><schemaDirectory>src/test/resources</schemaDirectory></configuration> 
    </plugin> 
1

另一種方式來設置的默認值可以是beforeMarshal(編組的Marshaller)函數:

private void beforeMarshal(Marshaller marshaller) { 
    childVal = (null == getChildVal) ? CHILD_VAL_DEFAULT_VALUE : childVal; } 
相關問題