2012-05-31 63 views
2

閱讀完this之後,我一直在試圖實現由RelaxNG XML驗證器(Jing)使用的自定義數據類型。我已經通過命令行成功運行了由Jing提供的示例實現(他們稱之爲datatype-sample),但我一直未能從java代碼中完成它。Jing RelaxNG驗證器和java代碼中的自定義數據類型庫

從命令行(視窗):

> set CLASSPATH=path\to\jing-20091111\bin\jing.jar;path\to\jing-20091111\sample\datatype\datatype-sample.jar 
> cd path\to\jing-20091111\sample\datatype 
> java com.thaiopensource.relaxng.util.Driver datatype-sample.rng valid.xml 

驗證沒有任何問題進行。但現在我想從下面的Java代碼使用相同的數據類型庫:

package rngdatatype; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.UnsupportedEncodingException; 
import javax.xml.XMLConstants; 
import javax.xml.transform.stream.StreamSource; 
import javax.xml.validation.Schema; 
import javax.xml.validation.SchemaFactory; 
import javax.xml.validation.Validator; 
import org.xml.sax.SAXException; 

public class Main { 

    public static void main(String[] args) throws UnsupportedEncodingException, FileNotFoundException, SAXException, IOException { 
     // make sure our jars are on classpath 
     System.out.println("Classpath: " + System.getProperty("java.class.path")); 

     // args 
     String rng = args[0]; 
     String xml = args[1]; 
     File rngFile = new File(rng); 
     File xmlFile = new File(xml); 

     // setup rng validator through JAXP 
     System.setProperty(SchemaFactory.class.getName() + ":" + XMLConstants.RELAXNG_NS_URI, "com.thaiopensource.relaxng.jaxp.XMLSyntaxSchemaFactory"); 
     SchemaFactory rngSchemaFactory = SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI); 

     // obtain a schema object 
     InputStreamReader rngReader = new InputStreamReader(new FileInputStream(rngFile), "UTF-8"); 
     Schema schema = rngSchemaFactory.newSchema(new StreamSource(rngReader)); 

     // validate using schema based validator 
     Validator validator = schema.newValidator(); 
     InputStreamReader xmlReader = new InputStreamReader(new FileInputStream(xmlFile), "UTF-8"); 
     validator.validate(new StreamSource(xmlReader)); 
    } 
} 

有了第一個參數是與以下內容的文件的路徑:

<element name="balancedString" 
    xmlns="http://relaxng.org/ns/structure/1.0" 
    datatypeLibrary="http://www.thaiopensource.com/relaxng/datatypes/sample"> 
    <data type="balancedString"/> 
</element> 

,第二個參數被以下內容的文件的路徑:

<balancedString>foo(bar(baz))</balancedString> 

這給了我下面的輸出:

Classpath: path\to\RNGDataType\lib\datatype-sample.jar;path\to\RNGDataType\lib\jing.jar;path\to\RNGDataType\build\classes;path\to\RNGDataType\src 
Exception in thread "main" org.xml.sax.SAXParseException: datatype library "http://www.thaiopensource.com/relaxng/datatypes/sample" not recognized 
... 

這清楚地表明數據類型無法解析。就我所知,滿足此要求的唯一要求(在類路徑上同時具有jing.jardatatype-sample.jar)已得到滿足。那麼我做錯了什麼?

P.S:上面的代碼工作,你必須把jing.jardatatype-sample.jar在CLASSPATH並提供論據它放在第一個是路徑datatype-sample.rng,第二個是路徑valid.xmlinvalid.xml。所有這些都與Jing分銷。

EDIT1:上面的程序也沒有我的IDE之外時爲JAR(java -jar)用適當的MANIFEST.MF文件運行工作。類路徑手動設置時也不起作用(java -classpath)。所以我懷疑實際的代碼有問題。

回答

2

似乎通過JAXP API通過Jing使用自定義數據類型庫已被破壞。即使它應該,它也不起作用。也許一些額外的屬性需要設置的地方,我只是沒有意識到這一點。

所以我想通過模仿Jing的com.thaiopensource.relaxng.util.Driver找到解決方法,因此使用Jing自己的API來執行驗證。請注意,這樣做會限制您的代碼,因此它僅適用於Jing。

package rngdatatype; 

import com.thaiopensource.validate.SchemaReader; 
import com.thaiopensource.validate.ValidationDriver; 
import com.thaiopensource.validate.auto.AutoSchemaReader; 
import java.io.File; 
import java.io.IOException; 
import org.xml.sax.InputSource; 
import org.xml.sax.SAXException; 

public class JingApi { 

    public static void main(String[] args) throws SAXException, IOException { 
     String rng = args[0]; 
     String xml = args[1]; 
     File rngFile = new File(rng); 
     File xmlFile = new File(xml); 

     SchemaReader sr = new AutoSchemaReader(); 
     ValidationDriver driver = new ValidationDriver(sr); 
     InputSource inRng = ValidationDriver.fileInputSource(rngFile); 
     inRng.setEncoding("UTF-8"); 
     driver.loadSchema(inRng); 
     InputSource inXml = ValidationDriver.fileInputSource(xmlFile); 
     inXml.setEncoding("UTF-8"); 
     driver.validate(inXml); 
    } 
} 

這使您能夠根據使用自定義數據類型庫的RNG模式從Java代碼驗證您的XML文件。請注意,前面提到的Diver類不能直接使用。

上面的程序使用與我自己的問題中的示例相同的類路徑和參數。

Edit1 -------------------------------------------- -

在擺弄了一會兒之後,我發現需要設置屬性才能讓我的JAXP示例與Jing一起使用自定義數據類型庫。

rngSchemaFactory.setProperty("http://relaxng.org/properties/datatype-library-factory", new org.relaxng.datatype.helpers.DatatypeLibraryLoader()); 

這是利用京本地API一個更優雅的解決方案:只要你獲得的SchemaFactory的實例後添加以下行。

/Edit1 ------------------------------------------- -

0

你的JAR文件必須包括額外的元數據文件的形式META-INF /服務/ org.relaxng.datatype.DatatypeLibraryFactory,其中必須包含實現接口org.relaxng.datatype.DatatypeLibraryFactory類的名稱

+0

它已經這樣做了。正如解釋的'datatype-sample.jar'是Jing的實現者的一個示例數據類型庫實現,它具有您的建議。否則,從命令行運行示例也不起作用。 – predi