使用XML Schema(xsd)验证输出XML

Pie*_*lov 15 xml validation schema xsd sas

我在SAS程序中创建了简单的XML文件:

data _null_;
   file "C:\persons.xml";
   put "<?xml version=""1.0"" encoding=""UTF-8""?>";
   put "<Person>";
   put "<Name>John</Name>";
   put "<Age>32</Age>";
   put "</Person>";
run;
Run Code Online (Sandbox Code Playgroud)

我有XML Schema(xsd文件).我想用模式验证我的文件,如果文件与shema不匹配则输入错误.可能吗?

提前致谢!

Sal*_*ale 2

正如 @robert-penridge 提到的,存在一种称为 XMLv2 引擎的东西。但是,无法直接在 SAS 中验证它,因为 XMLv2 引擎不会根据 xsd 验证 xml,并且它假定它是正确的 XML...

有一种方法可以使用 JAVA 和 SAS 来实现(适用于 SAS 9.3+,不确定早期版本)。因此,您需要将此 java 文件放置在可以通过 SAS 访问的位置。

Java 代码(必须命名为XMLValidator.java):

import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.*;
import org.xml.sax.SAXException;
import java.io.File;
import java.io.IOException;

class XMLValidator{

    File schemaFile;
    File xmlFile;
    XMLValidator(String pathXSD, String pathXML){
        this.schemaFile = new File(pathXSD);
    this.xmlFile=new File(pathXML);
    }

public int validate(){
    Source xmlSource = new StreamSource(xmlFile);
    SchemaFactory schemaFactory = SchemaFactory
        .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    try {
        Schema schema = schemaFactory.newSchema(schemaFile);
        Validator validator = schema.newValidator();
        validator.validate(xmlSource);
        return 0; // schema is valid
        } catch (SAXException e) {
        System.out.println(xmlSource.getSystemId() + " is NOT valid reason:" + e);
        return 1; // schema is not valid
    } catch (IOException e) {
        return 2;
    }
        }
    public static void main(String [ ] args){
        XMLValidator validator=new XMLValidator(args[1],args[2]);
        System.out.println(validator.validate());
    }
}
Run Code Online (Sandbox Code Playgroud)

编译时(使用javac XMLValidator.java),请记住保存它的路径。

现在您可以使用以下 SAS 代码来验证 XML:

%macro init_classpath_update;
  DATA _null_;
      LENGTH  path_separator $ 2
              orig_classpath $ 32767;

      DECLARE JavaObj f("java.io.File", "");
      f.getStaticStringField("pathSeparator", path_separator);

      orig_classpath = STRIP(SYSGET("CLASSPATH"));

      IF _ERROR_ = 1 OR LENGTH(orig_classpath) = 0 THEN DO;
      PUT "NOTE: Ignore any messages from the next statement(s)";
          orig_classpath = "";
    END;

      CALL SYMPUTX('CP_orig_classpath', STRIP(orig_classpath), 'GLOBAL');
      CALL SYMPUTX('CP_path_separator', COMPRESS(path_separator), 'GLOBAL');
  RUN;
%mend;

%macro add_to_classpath(cp_addition);
  DATA _null_;
      LENGTH  current_classpath $ 32767
              new_classpath $ 32767;

      current_classpath = STRIP(SYSGET("CLASSPATH"));

      IF _ERROR_ = 1 OR LENGTH(current_classpath) = 0 THEN DO;
      PUT "NOTE: Ignore any messages from the nearby statement(s)";
          new_classpath = "&cp_addition";
    END;
      ELSE DO;
          new_classpath = COMPRESS(current_classpath) || "&CP_path_separator" || "&cp_addition";
    END;

      CALL SYMPUTX('CP_new_classpath', STRIP(new_classpath), 'GLOBAL');
  RUN;

  %PUT NOTE: Setting Java classpath to &CP_new_classpath;
  OPTIONS SET=CLASSPATH "&CP_new_classpath";
%mend;

%macro reset_classpath;
  %PUT NOTE: Setting Java classpath back to its original state: &CP_orig_classpath;
  OPTIONS SET=CLASSPATH "&CP_orig_classpath";
%mend;

proc javainfo;
run;

%init_classpath_update;
%add_to_classpath(<path_where_you_saved_your_compiled_XMLValidator_file>/.);

data _null_;
     length rtn_val 8;
   declare javaobj xsdPath("java/lang/String","<path_to_your_xsd_file_as_absolute_path>");
   declare javaobj xmlPath("java/lang/String","<path_to_your_xml_file_as_absolute_path>");
   declare javaobj xmlValidator("XMLValidator",xsdPath,xmlPath);
   rc = xmlValidator.callIntMethod("validate",rtn_val);
   xsdPath.delete();
   xmlPath.delete();
   xmlValidator.delete();
  putlog rc= rtn_val=;
run;
Run Code Online (Sandbox Code Playgroud)

如果验证成功,此代码将返回0 ;如果验证失败,则返回12 。