Validate output XML with XML Schema (xsd) Validate output XML with XML Schema (xsd) xml xml

Validate output XML with XML Schema (xsd)


As @robert-penridge mentioned, there exist something called XMLv2 engine. However, it is not possible to validate it directly in SAS, as XMLv2 engine does not validate xml against xsd, and it assumes it is a proper XML...

There is a way to do it with JAVA and SAS (works for SAS 9.3+, not sure about earlier versions).So, you need to place this java file somewhere where you can reach it through SAS.

Java Code (has to be named 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());    }}

When compiled (with javac XMLValidator.java), remember the path where you saved it.

Now you can use the following SAS Code to validate 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);   xmlValidator.delete();   xmlPath.delete();   xmlValidator.delete();  putlog rc= rtn_val=;run;

This code will return 0 if the validation is successful, and 1 or 2 if the validation has failed.