XSD与Java验证器“minOccurs”无法按预期工作

时间:2016-08-18 18:17:03

标签: java xml xsd

我正在努力为我在工作中创建的工具添加XSD验证器功能。该工具实际上生成了一个格式非常严格的XML。 XML的格式在映射文档中定义,并且还有XSD架构。

我想要的是为用户添加快速验证他们在工具中创建的XML的能力。我添加了所有用于此验证的代码。不幸的是,我遇到了一些意想不到的问题。

具体来说,XML的一个部分大约有20个标签。这些标记并不总是出现在XML文件中,许多是可选的。如果它们不存在,我需要验证忽略可选标记 - 而是验证器返回错误即使我将“Minoccurs”值设置为0。

这是我的验证码:

package misc;

import java.io.File;
import java.io.IOException;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
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 XMLValidation {


    public static JFileChooser uploadFile;


    public static boolean validateXMLSchema(String xsdPath, String xmlPath){

        try{

            SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

            Schema schema = factory.newSchema(new File(xsdPath));
            Validator validator = schema.newValidator();
            validator.validate(new StreamSource(new File(xmlPath)));


        }catch(IOException | SAXException e){


            JOptionPane.showMessageDialog(null, e.getMessage());

            return false;

        }   

        JOptionPane.showMessageDialog(null, "No errors detected!");

        return true;

    }

    public static void uploadFile(){

        boolean uploadApproval = false;

        while(uploadApproval==false){//While upload approval has not been given..

            JFileChooser chooser = new JFileChooser();//Creates a new object of the JFileChooser class. 

            uploadFile = chooser;//Saves the upload file variable as the chooser response. 

            FileNameExtensionFilter filter = new FileNameExtensionFilter("XML Files", "xml");
            //Sets the allowed file formats for upload. 

            chooser.setFileFilter(filter);//Activates the created file filter.

            chooser.setDialogTitle("Select a Camt54 file to validate");//Sets the title bar text. 

            //Completes once the user clicks ok. 
            int returnVal = chooser.showOpenDialog(chooser);//
            if(returnVal == JFileChooser.APPROVE_OPTION){
                uploadApproval=true;
            }else{
                System.exit(0);
            }

            }
        }

}

由于安全性,我无法共享整个XSD架构。我试图拿出一部分来说明我的意思:

<xs:complexType name="CntsRecord1">
        <xs:sequence>
            <xs:element maxOccurs="1" minOccurs="0" name="test1" type="ISODateTime"/>
            <xs:element maxOccurs="1" minOccurs="0" name="test2" type="ISODateTime"/>
            <xs:element maxOccurs="1" minOccurs="0" name="test3" type="ISODateTime"/>
            <xs:element maxOccurs="1" minOccurs="0" name="test4" type="type4"/>
            <xs:element maxOccurs="1" minOccurs="0" name="test5" type="Max35Text"/>    
            <xs:element maxOccurs="1" minOccurs="0" name="test6" type="Max140Text"/>
            <xs:element maxOccurs="1" minOccurs="0" name="test7" type="type5"/>
            <xs:element maxOccurs="1" minOccurs="0"  name="Test" type="Max140Text"/>    

        </xs:sequence>
    </xs:complexType>

如您所见,所有这些值的“minOccurs”都设置为0,因此它们不应返回错误。

一旦我运行此代码,我将收到一个错误,即“Test”元素是预期的。 (假设所有其他人都在场)。

使用xsd运行验证并使用最小值0?

是否存在一些困难

以下是我从验证器返回的错误:

cvc-complex-type.2.4.a:Invalid content was found starting with element 'Test10'. One of {"urn:iso:std:iso:20022:tech:xsd:camt:054:001:04:"Test}' is expected.

以下是我的XML文件中的示例:

-<Cnts>

<Test1>2016-08-18T09:51:41</Test1>

<Test2>2016-08-18T09:51:41</Test2>

<Test3>2016-08-18T09:51:41</Test3>

<Test4>PAPER</Test4>

<Test5>2016-08-18T09:51:41</Test1>

<Test6>2016-08-18T09:51:41</Test2>

<Test7>2016-08-18T09:51:41</Test3>

<Test10>PAPER</Test4>

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

首先,您的XML和XSD不同意test元素的大小写,并且您的XML格式不正确。

但是,假设这些问题仅仅是您尝试清理敏感数据以创建可以安全发布的示例的工件,您的实际问题归结为理解此错误消息:

  

cvc-complex-type.2.4.a:从元素'Test10'开始发现无效内容。其中一个{“urn:iso:std:iso:20022:tech:xsd:camt:054:001:04:”Test}'预期

是的,因为Test声明为minOccurs="0",所以它确实是可选的。错误并非如此。它说解析器在成功解析Test7后遇到了一个元素,而该元素不是它 期望 的元素。 预期跟随Test7成为Test的元素,因为根据您的XSD,这是 可能 (不是必须)出现在那里。

答案 1 :(得分:0)

你的代码肯定比这更新,但如果你想回到旧的Xerces,Xerces验证似乎没有minOccurs = 0的问题。此链接提供了一个教程:http://www.onjava.com/pub/a/onjava/2004/09/15/schema-validation.html

示例代码:

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.io.IOUtils;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

    System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    factory.setValidating(true);
    factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
    factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", schemaUrl);
    DocumentBuilder builder = factory.newDocumentBuilder();
    Validator handler = new Validator();
    builder.setErrorHandler(handler);
    builder.parse(IOUtils.toInputStream(xmlString));
    if (handler._validationError) {
        StringBuilder xmsg = new StringBuilder();
        for (SAXParseException exception : handler.getExceptions()) {
            xmsg.append(exception.getMessage());
            xmsg.append("\n");
        }
        //show xmsg in your dialog
    }