2011-03-24 17 views
5

Öğeler ve öznitelikler için varsayılan değerleri tanımlayan bir şema var. Bu şemaya dayanarak JAXB kullanarak bir belgeyi ayrıştırmaya çalışıyorum ancak JAXB varsayılan değerleri ayarlamıyor. JAXB'nin şemadan varsayılan değerleri nasıl kazanacağına dair herhangi bir fikir var mı?JAXB varsayılan şema değerlerini destekliyor mu?

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; 
    } 

} 

cevap

9

Eleman Varsayılan Değer

aşağıdaki gibi ek açıklama için gereken eleman mülkiyet varsayılan değeri almak için:

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

Öznitelik Varsayılan Değer

EclipseLink JAXB (MOXy) kullanırsanız, sağladığınız kodu kullanarak varsayılan özellik değerini alırsınız. JAXB'nin Metro uygulamasında, bunun çalışmasını engelleyen bir hata olabilir. Not MOXy uygulamasına öncülük ediyorum.


Alternatif Yaklaşım

Aşağıdaki kod modeline kod değişiklikleri gerektirmeden herhangi JAXB uygulanması ile birlikte çalışmalıdır.

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

Ben özellikle Basit Elements vs Özelliğine Sahip Olan uyum olması gibi mantıklı yapmaya çalıştığımız şey bulmak: Aşağıdaki ve kaldıraç SAXSource yapabilirdi. Bana garip geliyor, ama jaxb2 uygulamacıları, istenen davranışı elde etmek için eklemeniz gereken ekstra bir uzantı grubu eklemeyi tercih ediyor. Bkz:.

(Daha doğrusu Özellikler ve en azından basit türleri Elements arasında daha doğal varsayılan davranışları ve tutarlılığı görecekti - bir eklenti kayıt olma zorunluluğu olmadan Sonra fiş sağlamak -özel durumlar için. Bu neden yapılmadı sadece benim ya da geriye dönük uyumluluk benim sadece çocuklar - bir tahmin.)

jaxb2-commons varsayılan değer eklentisi, eklediğiniz ek komutlar (ve kavanozlar) anlamına gelir. Sırayla xjc, varsayılan davranışları ekler Alana.(. Tabii, koşullu boş çek varsayılan değer ya da değil sunar): Benim durumumda

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

Blaise Doughan kullanarak etrafında bir pratik iş gibi görünüyor. XML belgenizin doğasına bağlı olarak, bu mükemmel olabilir.

Yine de, bu Varsayılan Değer eklentisi, çözümü oluşturma işlemine taşıyabiliyor ve kodunuzda bir değişiklik göremiyor gibi görünüyor (Blaise önerilen Sax ayrıştırıcısının aksine bir Dom kullandığınızı varsayarak).

Varsayılan değer eklentisi sorunu çözüyor ve olasılıkla daha fazla programatik varsayılan değer denetimi xjc'yi çalıştırmanız gerektiğinde olası bir durumda ek genişletilebilirlik (bu tür gelişmiş özelliğe ihtiyaç duyulmuyor) sağlayabilir. İşte

yardımcı olur durumunda bir maven yapılandırma snippet'tir:

<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

bir beforeMarshal (Marshaller diziciyi) işlevi olabilir varsayılan değer oluşturmaya yönelik bir başka yolu:

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