如何用XML SCHEMA 驗證xml文?

輔導同事讓我寫一個能夠簡單驗證XML文的程序。由於只要求能xml文裏有開始有結束標籤就算正確的格式。我在網上找了很長時間也沒有找到這樣的工具和程序。不過發現一個可以嚴格限制xml文的 SCHEMA ,不過這個需要用到dom4j 源代碼如下。感覺寫的非常好。

package cn.com.starit.DB;

import java.io.File;
import java.io.FileWriter;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.SAXValidator;
import org.dom4j.io.XMLWriter;
import org.dom4j.util.XMLErrorHandler;

public class ValidateXML {
 public static void validateXMLByXSD(String xsdFileName,String xmlFileName) {
        try {
            //創建默認的XML錯誤處理器
            XMLErrorHandler errorHandler =  new XMLErrorHandler();
          
            //獲取基於 SAX 的解析器的實例
            SAXParserFactory factory = SAXParserFactory.newInstance();
            //解析器在解析時驗證 XML 內容。
            factory.setValidating(true);
            //指定由此代碼生成的解析器將提供對 XML 名稱空間的支持。
            factory.setNamespaceAware(true);
            //使用當前配置的工廠參數創建 SAXParser 的一個新實例。
            SAXParser parser = factory.newSAXParser();
            //創建一個讀取工具
            SAXReader xmlReader = new SAXReader();
            //獲取要校驗xml文檔實例
            Document xmlDocument = (Document) xmlReader.read(new File(xmlFileName));
            //設置 XMLReader 的基礎實現中的特定屬性。核心功能和屬性列表可以在 [url]http://sax.sourceforge.net/?selected=get-set[/url] 中找到。
            parser.setProperty(
                    "http://java.sun.com/xml/jaxp/properties/schemaLanguage",
                    "http://www.w3.org/2001/XMLSchema");
            parser.setProperty(
                    "http://java.sun.com/xml/jaxp/properties/schemaSource",
                    "file:" + xsdFileName);
            //創建一個SAXValidator校驗工具,並設置校驗工具的屬性
            SAXValidator validator = new SAXValidator(parser.getXMLReader());
            //設置校驗工具的錯誤處理器,當發生錯誤時,可以從處理器對象中得到錯誤信息。
            validator.setErrorHandler(errorHandler);                   
           
            //校驗
            validator.validate(xmlDocument);
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("UTF-8");
            XMLWriter writer = new XMLWriter( new
            FileWriter(new File("d://err.xml")), format);

            //  TODO     XMLWriter writer = new XMLWriter(OutputFormat.createPrettyPrint());
            //如果錯誤信息不爲空,說明校驗失敗,打印錯誤信息
            if (errorHandler.getErrors().hasContent()) {
                System.out.println("XML文件通過XSD文件校驗失敗!");
                // ** 將document中的內容寫入文件中 *//*
                writer.write(errorHandler.getErrors()); //writer.write(parse(document));           
                writer.close();              
            } else {
                System.out.println("Good! XML文件通過XSD文件校驗成功!");
            }
        } catch (Exception ex) {
            System.out.println("XML文件: " + xmlFileName + " 通過XSD文件:" + xsdFileName + "檢驗失敗。/n原因: " + ex.getMessage());
            ex.printStackTrace();
        }
    }

  public static void main(String[] args) {
       String xsdpath = "e://test1.xsd";
       String xmlpath = "e://test1.xml";
       validateXMLByXSD(xsdpath,xmlpath);
  }

///************驗證字符串[xml 字符串 轉化成 輸入流] start****************/
//
//// xmlMsg爲xml文檔<?xml version="1.0" encoding="GBK"?>........
//InputStream in = new ByteArrayInputStream(xmlMsg);
//
//然後將上面的reader.read("message.xml") 改爲 reader.read(in)就OK了。
//
///************驗證字符串[xml 字符串 轉化成 輸入流] end ****************/
}

 

不過還是遇到一個問題。我們的xml文裏(其實沒有我把小寫L看成1)有數字節點,我就想到可以用正則表達式來替換啊~可惜我對正則很陌生。怎麼辦上網查找看有沒有能夠快速入門的。上網找了半天,終於找到一個可以三十分鐘就可以入門的教程。寫的確實不錯。不過我感覺看完了還是一頭霧水。不過基本的概念已經有了,別人寫的差不多可以看懂了。下面大概記一下基本的正則元字符的意思,以後做複習和查找之用。

表1.常用的元字符
代碼說明
. 匹配除換行符以外的任意字符
/w 匹配字母或數字或下劃線或漢字
/s 匹配任意的空白符
/d 匹配數字
/b 匹配單詞的開始或結束
^ 匹配字符串的開始
$ 匹配字符串的結束

表2.常用的限定符
代碼/語法說明
* 重複零次或更多次
+ 重複一次或更多次
? 重複零次或一次
{n} 重複n次
{n,} 重複n次或更多次
{n,m}

重複n到m次

例子: 1.要找的是hi後面不遠處跟着一個Lucy,你應該用/bhi/b.*/bLucy/b /b並不匹配這些單詞分隔符中的任何一個,它只匹配一個位置 .就是匹配除換行任何字符,*出現重複零次或更多次。

           2.要查找hi就更容易了/bhi/b

           3.0/d{2}-/d{8}的意思是0 這裏/d後面的{2}({8})的意思是前面/d必須連續重複匹配2次(8次)。

           4./b/w{6}/b 匹配剛好6個字母/數字的單詞

           5.^/d{5,12}$匹配5到12個數字。

           6./(?0/d{2}[) -]?/d{8}這個很好例子看懂就說明前面掌握的差不多了

轉義:如果你想查找元字符本身的話,比如你查找.,或者*,就出現了問題:你沒法指定它們,因爲它們會被解釋成其它的意思。這時你就必須使用/來取消這些字符的特殊意義。因此,你應該使用/.和/*。當然,要查找/本身,你也得用//.

反義:

表3.常用的反義代碼
代碼/語法說明
/W 匹配任意不是字母,數字,下劃線,漢字的字符
/S 匹配任意不是空白符的字符
/D 匹配任意非數字的字符
/B 匹配不是單詞開頭或結束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou這幾個字母以外的任意字符

例如:

       1./S+匹配不包含空白符的字符串。

       2.<a[^>]+>匹配用尖括號括起來的以a開頭的字符串。

 

替換:具體方法是用|把不同的規則分隔開

/(0/d{2}/)[- ]?/d{8}|0/d{2}[- ]?/d{8}這個表達式匹配3位區號的電話號碼,其中區號可以用小括號括起來,也可以不用,區號與本地號間可以用連字號或空格間隔,也可以沒有間隔。你可以試試用替換|把這個表達式擴展成也支持4位區號的。

後向引用:規則是:從左向右,以分組的左括號爲標誌,第一個出現的分組的組號爲1,第二個爲2,以此類推。

/1代表分組1匹配的文本 /b(/w+)/b/s+/1/b可以用來匹配重複的單詞,像go go, kitty kitty。首先是一個單詞,也就是單詞開始處和結束處之間的多於一個的字母或數字(/b(/w+)/b),然後是1個或幾個空白符(/s+),最後是前面匹配的那個單詞(/1)。

例如:1./b(/w+)/b/s+/1/b可以用來匹配重複的單詞,像go go, kitty kitty

         2./b(?<Word>/w+)/b/s+/k<Word>/b。請使用這樣的語法:(?<Word>/w+)(或者把尖括號換成’也行:(?’Word’/w+)),這樣就把/w+的組名指定爲Word了。要反向引用這個分組捕獲的內容,你可以使用/k<Word>

 

表4.分組語法
捕獲
(exp) 匹配exp,並捕獲文本到自動命名的組裏
(?<name>exp) 匹配exp,並捕獲文本到名稱爲name的組裏,也可以寫成(?’name’exp)
(?:exp) 匹配exp,不捕獲匹配的文本,也不給此分組分配組號
零寬斷言
(?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp後面的位置
(?!exp) 匹配後面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置

 

(?=exp)也叫零寬度正預測先行斷言,它斷言自身出現的位置的後面能匹配表達式exp。比如/b/w+(?=ing/b),匹配以ing結尾的單詞的前面部分(除了ing以外的部分),如查找I’m singing while you’re dancing.時,它會匹配sing和danc。

(?<=exp)也叫零寬度正回顧後發斷言,它斷言自身出現的位置的前面能匹配表達式exp。比如(?<=/bre)/w+/b會匹配以re開頭的單詞的後半部分(除了re以外的部分),例如在查找reading a book時,它匹配ading。

假如你想要給一個很長的數字中每三位間加一個逗號(當然是從右邊加起了),你可以這樣查找需要在前面和裏面添加逗號的部分:((?<=/d)/d{3})*/b,用它對1234567890進行查找時結果是234567890。

 

就這樣已經入門了

下面是一個把xml文裏面的數字節點轉換成字符節點如下

        String str = "<?xml version=/"1.0/" encoding=/"GB2312/"?>"
   + "<esb>"
   + "<route>"
    +"<from>"+ 123+ "</from>"        // 確認消息中,to/from 與接收信息剛好相反
    +"<to>"+ 123+ "</to>"
    +"<type>"+231+ "</type>"
    +"<area>"+ 123+ "</area>"
   + "</route>"
   + "<public>"
    +"<ds_msg>"
     +"<time>"+ 123+ "</time>"
     +"<ds_msg_id>"+ 456+ "</ds_msg_id> "
     +"<ds_msg_class>"+"<13/>"+"</ds_msg_class>"
    +"</ds_msg>"
   + "</public>"
   +""
   
  + "</esb>".replaceAll("<[//]?[0-9]+[//]?>", "<java1/>");
        String regex="(</?)(//d+)(/?>)";
        String result=str.replaceAll(regex,"$1v$2$3");

 

感謝以爲csdn上的朋友提供的http://www.alixixi.com/web/a/2008123144264.shtml#

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章