针对Java中的XSD验证XML
有許多工具可用于根據XSD 驗證XML文檔 。 其中包括操作系統腳本和工具,例如xmllint ,XML編輯器和IDE,甚至是在線驗證器。 由于前面提到的方法的局限性或問題,我發現擁有自己的易于使用的XML驗證工具很有用。 Java使編寫這樣的工具變得容易,并且這篇文章演示了用Java開發簡單的XML驗證工具是多么容易。
本文中開發的Java工具需要JDK8。但是,可以很容易地修改簡單的Java應用程序,使其可以與JDK 7或什至與JDK 5一樣舊的Java版本一起使用。在大多數情況下,我嘗試對需要JDK 7或JDK 8識別這些依賴關系并在Java的早期版本中提供替代方法的代碼。 我這樣做是為了使該工具即使在具有舊版Java的環境中也可以工作。
本文結尾討論了本文討論的基于Java的XML驗證工具的完整代碼清單。 接下來顯示當討論針對一個或多個XSD的XML驗證時,該應用程序中最重要的代碼行。
使用Java針對XSD驗證XML的本質
final Schema schema = schemaFactory.newSchema(xsdSources); final Validator validator = schema.newValidator(); validator.validate(new StreamSource(new File(xmlFilePathAndName)));前面的代碼清單顯示了標準JDK中可用的直接方法,用于根據XSD驗證XML。 通過調用javax.xml.validation.SchemaFactory.newSchema(Source []) (其中javax.xml.transform.Source對象的數組表示一個或多個XSD)來實例化javax.xml.validation.Schema的實例。 通過Schema的newValidator()方法從Schema實例中獲取javax.xml.validation.Validator的實例。 可以將要驗證的XML傳遞到Validator的validate(Source)方法,以針對最初提供給使用SchemaFactory.newSchema(Source[])創建的Schema對象的XSD或XSD執行XML驗證。
下一個代碼清單包括剛剛突出顯示的代碼,但表示該代碼所駐留的整個方法。
validateXmlAgainstXsds(String,String [])
/*** Validate provided XML against the provided XSD schema files.** @param xmlFilePathAndName Path/name of XML file to be validated;* should not be null or empty.* @param xsdFilesPathsAndNames XSDs against which to validate the XML;* should not be null or empty.*/ public static void validateXmlAgainstXsds(final String xmlFilePathAndName, final String[] xsdFilesPathsAndNames) {if (xmlFilePathAndName == null || xmlFilePathAndName.isEmpty()){out.println("ERROR: Path/name of XML to be validated cannot be null.");return;}if (xsdFilesPathsAndNames == null || xsdFilesPathsAndNames.length < 1){out.println("ERROR: At least one XSD must be provided to validate XML against.");return;}final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);final StreamSource[] xsdSources = generateStreamSourcesFromXsdPathsJdk8(xsdFilesPathsAndNames);try{final Schema schema = schemaFactory.newSchema(xsdSources);final Validator validator = schema.newValidator();out.println( "Validating " + xmlFilePathAndName + " against XSDs "+ Arrays.toString(xsdFilesPathsAndNames) + "...");validator.validate(new StreamSource(new File(xmlFilePathAndName)));}catch (IOException | SAXException exception) // JDK 7 multi-exception catch{out.println("ERROR: Unable to validate " + xmlFilePathAndName+ " against XSDs " + Arrays.toString(xsdFilesPathsAndNames)+ " - " + exception);}out.println("Validation process completed."); }validateXmlAgainstXsds(String, String[])方法的代碼清單顯示了如何使用指定的架構類型( XMLConstants.W3C_XML_SCHEMA_NS_URI )獲得SchemaFactory實例。 此方法還處理在驗證過程中可能引發的各種類型的異常。 正如代碼中的注釋所指出的那樣,此方法使用了支持在單個catch子句中捕獲多個異常的JDK 7語言更改,但可以替換為單獨的catch子句或對早于JDK的代碼庫捕獲單個更通用的異常7。
剛剛顯示的方法調用了一個名為generateStreamSourcesFromXsdPathsJdk8(String[]) ,下一個清單是該調用的方法。
generateStreamSourcesFromXsdPathsJdk8(String [])
/*** Generates array of StreamSource instances representing XSDs* associated with the file paths/names provided and use JDK 8* Stream API.** This method can be commented out if using a version of* Java prior to JDK 8.** @param xsdFilesPaths String representations of paths/names* of XSD files.* @return StreamSource instances representing XSDs.*/ private static StreamSource[] generateStreamSourcesFromXsdPathsJdk8(final String[] xsdFilesPaths) {return Arrays.stream(xsdFilesPaths).map(StreamSource::new).collect(Collectors.toList()).toArray(new StreamSource[xsdFilesPaths.length]); }剛剛顯示的方法使用JDK 8流支持,根據路徑/名稱字符串所指向的XSD的內容,將表示XSD文件的路徑/名稱的字符串數組轉換為StreamSource的實例。 在該類的完整代碼清單中,還有一個不贊成使用的方法generateStreamSourcesFromXsdPathsJdk7(final String[]) ,該方法可以代替基于JDK 8的Java版本上的代碼使用此方法。
從命令行執行時,此單類Java應用程序最有用。 為此,定義了一個main功能,如下面的代碼清單所示。
可執行main(String [])函數
/*** Validates provided XML against provided XSD.** @param arguments XML file to be validated (first argument) and* XSD against which it should be validated (second and later* arguments).*/ public static void main(final String[] arguments) {if (arguments.length < 2){out.println("\nUSAGE: java XmlValidator <xmlFile> <xsdFile1> ... <xsdFileN>\n");out.println("\tOrder of XSDs can be significant (place XSDs that are");out.println("\tdependent on other XSDs after those they depend on)");System.exit(-1);}// Arrays.copyOfRange requires JDK 6; see// http://stackoverflow.com/questions/7970486/porting-arrays-copyofrange-from-java-6-to-java-5// for additional details for versions of Java prior to JDK 6.final String[] schemas = Arrays.copyOfRange(arguments, 1, arguments.length);validateXmlAgainstXsds(arguments[0], schemas); }如果傳遞給可執行文件的命令行參數少于兩個,則可執行文件main(String[])打印一條使用情況語句,因為它至少希望驗證XML文件的名稱/路徑以及要驗證的XSD的名稱/路徑。 XML反對。
main函數采用第一個命令行參數,并將其視為XML文件的路徑/名稱,然后將所有其余的command lin參數視為一個或多個XSD的路徑/名稱。
現在已經顯示了用于針對一個或多個XSD驗證XML的簡單Java工具(完整的代碼清單在文章底部)。 有了它,我們就可以對示例XML文件和關聯的XSD運行它。 在此演示中,我使用的是Servlet 2.5 web.xml 部署描述符的非常簡單的體現 。
樣本有效Servlet 2.5 web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"version="2.5"> <display-name>Sample Java Servlet 2.5 Web Application</display-name> </web-app>剛剛顯示的簡單web.xml文件對Servlet 2.5 XSD有效,并且運行此簡單的基于Java的XSD驗證工具的輸出證明不報告任何驗證錯誤。
使用此工具的XSD有效XML文件不會產生非常有趣的結果。 下一個代碼清單顯示了一個故意無效的web.xml文件,該文件具有未在關聯的Servlet 2.5 XSD中指定的“ title”元素。 代碼列表后顯示了輸出,其中突出顯示了錯誤消息的最重要部分。
樣本無效的Servlet 2.5 web.xml(web-invalid.xml)
<web-app xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"version="2.5"><display-name>Java Servlet 2.5 Web Application</display-name><title>A handy example</title> </web-app>
如最后一個輸出所示,當提供的XML無效時,在輸出方面,事情會變得更加有趣。
我想在此強調一個重要的警告。 有時需要以特定順序指定此基于Java的工具提供的XSD。 特別是,在包含其他XSD的XSD之后,應該在命令行上列出它們所包含的XSD。 換句話說,通常在命令行上提供不包含“包括”依賴項的XSD,然后再將包含它們的XSD提供給它們。
下一個代碼清單用于完整的XmlValidator類。
XmlValidator.java(完整的類列表)
package dustin.examples.xmlvalidation;import org.xml.sax.SAXException;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 java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors;import static java.lang.System.out;/*** Validate provided XML against the provided XSDs.*/ public class XmlValidator {/*** Validate provided XML against the provided XSD schema files.** @param xmlFilePathAndName Path/name of XML file to be validated;* should not be null or empty.* @param xsdFilesPathsAndNames XSDs against which to validate the XML;* should not be null or empty.*/public static void validateXmlAgainstXsds(final String xmlFilePathAndName, final String[] xsdFilesPathsAndNames){if (xmlFilePathAndName == null || xmlFilePathAndName.isEmpty()){out.println("ERROR: Path/name of XML to be validated cannot be null.");return;}if (xsdFilesPathsAndNames == null || xsdFilesPathsAndNames.length < 1){out.println("ERROR: At least one XSD must be provided to validate XML against.");return;}final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);final StreamSource[] xsdSources = generateStreamSourcesFromXsdPathsJdk8(xsdFilesPathsAndNames);try{final Schema schema = schemaFactory.newSchema(xsdSources);final Validator validator = schema.newValidator();out.println("Validating " + xmlFilePathAndName + " against XSDs "+ Arrays.toString(xsdFilesPathsAndNames) + "...");validator.validate(new StreamSource(new File(xmlFilePathAndName)));}catch (IOException | SAXException exception) // JDK 7 multi-exception catch{out.println("ERROR: Unable to validate " + xmlFilePathAndName+ " against XSDs " + Arrays.toString(xsdFilesPathsAndNames)+ " - " + exception);}out.println("Validation process completed.");}/*** Generates array of StreamSource instances representing XSDs* associated with the file paths/names provided and use JDK 8* Stream API.** This method can be commented out if using a version of* Java prior to JDK 8.** @param xsdFilesPaths String representations of paths/names* of XSD files.* @return StreamSource instances representing XSDs.*/private static StreamSource[] generateStreamSourcesFromXsdPathsJdk8(final String[] xsdFilesPaths){return Arrays.stream(xsdFilesPaths).map(StreamSource::new).collect(Collectors.toList()).toArray(new StreamSource[xsdFilesPaths.length]);}/*** Generates array of StreamSource instances representing XSDs* associated with the file paths/names provided and uses* pre-JDK 8 Java APIs.** This method can be commented out (or better yet, removed* altogether) if using JDK 8 or later.** @param xsdFilesPaths String representations of paths/names* of XSD files.* @return StreamSource instances representing XSDs.* @deprecated Use generateStreamSourcesFromXsdPathsJdk8 instead* when JDK 8 or later is available.*/@Deprecatedprivate static StreamSource[] generateStreamSourcesFromXsdPathsJdk7(final String[] xsdFilesPaths){// Diamond operator used here requires JDK 7; add type of// StreamSource to generic specification of ArrayList for// JDK 5 or JDK 6final List<StreamSource> streamSources = new ArrayList<>();for (final String xsdPath : xsdFilesPaths){streamSources.add(new StreamSource(xsdPath));}return streamSources.toArray(new StreamSource[xsdFilesPaths.length]);}/*** Validates provided XML against provided XSD.** @param arguments XML file to be validated (first argument) and* XSD against which it should be validated (second and later* arguments).*/public static void main(final String[] arguments){if (arguments.length < 2){out.println("\nUSAGE: java XmlValidator <xmlFile> <xsdFile1> ... <xsdFileN>\n");out.println("\tOrder of XSDs can be significant (place XSDs that are");out.println("\tdependent on other XSDs after those they depend on)");System.exit(-1);}// Arrays.copyOfRange requires JDK 6; see// http://stackoverflow.com/questions/7970486/porting-arrays-copyofrange-from-java-6-to-java-5// for additional details for versions of Java prior to JDK 6.final String[] schemas = Arrays.copyOfRange(arguments, 1, arguments.length);validateXmlAgainstXsds(arguments[0], schemas);} }盡管這篇文章的篇幅最初可能暗示了多少,但使用Java來針對XSD驗證XML還是相當簡單的。 此處顯示和解釋的示例應用程序試圖證明這一點,并且是針對指定XSD對XML文檔進行簡單命令行驗證的有用工具。 可以輕松地將其移植到Groovy,以使其更加腳本友好。 如前所述,這個簡單的工具需要當前編寫的JDK 8,但是可以很容易地改編為在JDK 5,JDK 6或JDK 7上運行。
翻譯自: https://www.javacodegeeks.com/2015/03/validating-xml-against-xsds-in-java.html
總結
以上是生活随笔為你收集整理的针对Java中的XSD验证XML的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 小米桌面天气怎么设置(小米桌面天气怎么设
 - 下一篇: 默认方法和多重继承