Avatar billede fredand Forsker
11. september 2006 - 15:26 Der er 12 kommentarer og
1 løsning

How to validate a xml with a xsd?

Hello!

I'm developing a EJB app. The idea is that the EJB should validate a xml-stucture with a xsd.

This was working fine until I needed to put it all in a jar-file.

The structure of the ejb.jar looks like:

com/myapp
META-INF
lib
resources/xmlskeletons
resourses/xsd

I populate a document build upon a xmlskeleton.
Then I would like to validate the xml-structure according to the xsd.

Before, when this was in a exploaded file structure, I could set the xsd-path as a element in the xml-structure.

But now when the xsd is inside the jar, and as you can see in the code below, the xsd-file will not be found.

So if you have any suggestions how to include the xsd for the validation from a jar please let me know!!

BTW I can just use Java 1.4

Best regards
Fredrik

    public boolean validateXML(String xml, String xsdFilePath, String nameSpace, String rootElementName)
    {
        try {
            //Build temporary document
            Document documentTemp = buildDocumentFromString(xml);

            //Set namespace and schemaLocation for validation this will not concern the paths in xml sent to IC
            setXmlElementAttribute(rootElementName, "xmlns", nameSpace, documentTemp);
            setXmlElementAttribute(rootElementName, "xsi:schemaLocation",
                                  nameSpace + " " + System.getProperty("user.dir") + "/" + xsdFilePath, documentTemp);

            //Transform document to xml String
            String tempXml = getXmlStringFromDocument(documentTemp);

            //Validate the xml String
            saxParseException = null;
            SAXParser parser = new SAXParser();

            //parser.setFeature("http://xml.org/sax/features/validation", true);
            parser.setFeature("http://apache.org/xml/features/validation/schema", true);
            parser.setFeature("http://apache.org/xml/features/validation/schema-full-checking", true);
            parser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", xsdFilePath);
            parser.setErrorHandler(this);
            parser.parse(new InputSource(new StringReader(tempXml)));

            if (saxParseException == null) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            printExceptionToFile("XML_EXCECPTION", e);

            return false;
        }
    }
Avatar billede arne_v Ekspert
11. september 2006 - 18:13 #1
have you tried:
            parser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", getClass().getClassLoader().getRessourceAsStrem("blabla.xsd"));

?
Avatar billede fredand Forsker
11. september 2006 - 18:34 #2
Hello!

Thanks for your reply! Must say that you are fenomenal!

I must say that it was a bit embarrasing of me that I did not think of that, that you have just helped me with.

How ever your answer seems to be the right way.

I just got this Exception now:

java.lang.ClassCastException: weblogic.utils.zip.SafeZipFileInputStream
    at org.apache.xerces.impl.xs.XMLSchemaLoader.reset(Lorg.apache.xerces.xni.parser.XMLComponentManager;)V(Unknown Source)
    at org.apache.xerces.impl.xs.XMLSchemaValidator.reset(Lorg.apache.xerces.xni.parser.XMLComponentManager;)V(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.configurePipeline()V(Unknown Source)
    at org.apache.xerces.parsers.XIncludeAwareParserConfiguration.configurePipeline()V(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Z)Z(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Lorg.apache.xerces.xni.parser.XMLInputSource;)V(Unknown Source)
    at org.apache.xerces.parsers.XMLParser.parse(Lorg.apache.xerces.xni.parser.XMLInputSource;)V(Unknown Source)
    at org.apache.xerces.parsers.AbstractSAXParser.parse(Lorg.xml.sax.InputSource;)V(Unknown Source)
    at com.myxml.XmlManager.validateXML(Ljava.lang.String;Ljava.lang.String;Ljava.lang.String;Ljava.lang.String;)Z(XmlManager.java:1683)


at:
parser.parse(new InputSource(new StringReader(tempXml)));

Do you maybe have any clue about this?

Best regards
Fredrik
Avatar billede arne_v Ekspert
11. september 2006 - 21:30 #3
ligner et eller andet super giftigt classloader classpath XML libraries version problem

prøv at hente det schema fra filen op i et byte[], wrap det i et ByteArrayInputStream
og kald med den
Avatar billede arne_v Ekspert
11. september 2006 - 21:30 #4
sorry for the danish
Avatar billede fredand Forsker
12. september 2006 - 09:01 #5
Hello!

I guess you mean like this then:

    public boolean validateXML(String xml, String xsdFilePath, String nameSpace, String rootElementName)
    {
        try {
            //Build temporary document
            Document documentTemp = buildDocumentFromString(xml);

            //Set namespace and schemaLocation for validation
            setXmlElementAttribute(rootElementName, "xmlns", nameSpace, documentTemp);
            setXmlElementAttribute(rootElementName, "xsi:schemaLocation",
                                  nameSpace + " " + System.getProperty("user.dir") + "/" + xsdFilePath, documentTemp);

            //Transform document to xml String
            String tempXml = getXmlStringFromDocument(documentTemp);

            //Validate the xml String
            saxParseException = null;
            SAXParser parser = new SAXParser();

            parser.setFeature("http://apache.org/xml/features/validation/schema", true);
            parser.setFeature("http://apache.org/xml/features/validation/schema-full-checking", true);


            java.io.InputStream is = getClass().getClassLoader().getResourceAsStream(xsdFilePath);

            byte[] xsdByte = new byte[is.available()];
            is.read(xsdByte);
            java.io.ByteArrayInputStream byteArrayInputStream = new java.io.ByteArrayInputStream(xsdByte);

            parser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", byteArrayInputStream );

            parser.setErrorHandler(this);
            parser.parse(new InputSource(new StringReader(tempXml)));

            if (saxParseException == null) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            printExceptionToFile("XML_EXCECPTION", e);

            return false;
        }
    }

How ever this gave me this exception:

java.lang.ClassCastException: java.io.ByteArrayInputStream
    at org.apache.xerces.impl.xs.XMLSchemaLoader.reset(Lorg.apache.xerces.xni.parser.XMLComponentManager;)V(Unknown Source)
    at org.apache.xerces.impl.xs.XMLSchemaValidator.reset(Lorg.apache.xerces.xni.parser.XMLComponentManager;)V(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.configurePipeline()V(Unknown Source)
    at org.apache.xerces.parsers.XIncludeAwareParserConfiguration.configurePipeline()V(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Z)Z(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Lorg.apache.xerces.xni.parser.XMLInputSource;)V(Unknown Source)
    at org.apache.xerces.parsers.XMLParser.parse(Lorg.apache.xerces.xni.parser.XMLInputSource;)V(Unknown Source)
    at org.apache.xerces.parsers.AbstractSAXParser.parse(Lorg.xml.sax.InputSource;)V(Unknown Source)
    at com.mypack.jms.controller.XmlManager.validateXML(Ljava.lang.String;Ljava.lang.String;Ljava.lang.String;Ljava.lang.String;)Z(XmlManager.java:1718)
    at com.mypack.jms.controller.ReportManagerMDB.partGenerateXmlRapport(Lcom.mypack.jms.model.BusinessObjectInfo;Ljava.util.Properties;Lcom.mypack.jms.controller.MxMgr;)Ljava.lang.String;(ReportManagerMDB.java:478)
    at com.mypack.jms.controller.ReportManagerMDB.createBusinessObjectReport(Lcom.mypack.jms.model.BusinessObjectInfo;)V(ReportManagerMDB.java:112)
    at com.mypack.jms.controller.ReportManagerMDB.onMessage(Ljavax.jms.Message;)V(ReportManagerMDB.java:71)
    at weblogic.ejb20.internal.MDListener.execute(Lweblogic.kernel.ExecuteThread;)V(MDListener.java:370)
    at weblogic.kernel.ExecuteThread.execute(Lweblogic.kernel.ExecuteRequest;)V(ExecuteThread.java:219)
    at weblogic.kernel.ExecuteThread.run()V(ExecuteThread.java:178)
    at java.lang.Thread.startThreadFromVM(Ljava.lang.Thread;)V(Unknown Source)

I guess this means that this method does not expect a ByteArrayInputStream:

parser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", byteArrayInputStream );

What do you think?

Perhaps I need to look at any other xml-package for validation with xml and xsd.

Best regards
Fredrik
Avatar billede arne_v Ekspert
12. september 2006 - 21:37 #6
nothing wrog with Xerces - I use that myself

but what version of Xerces are you using ?
Avatar billede arne_v Ekspert
12. september 2006 - 21:43 #7
some googling indicates that this exception is a misleading exception text

and that it ha ssomething to do with a missing namespace specification

does your XML use namespace ??
Avatar billede fredand Forsker
13. september 2006 - 13:02 #8
Hello!

Do you mean that you can validate a xml from a xsd, when your app and the xsd is packed inside a jar?

I decompiled XMLSchemaLoader and in the reset method they do this:
fExternalNoNSSchema = (String)xmlcomponentmanager.getProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation");

I guess this is where the ClassCastException takes place since I do:
parser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", byteArrayInputStream );

It looks like they are expecting a String, probably a path to the xsd.

Below is one example of my XML:
<?xml version="1.0" encoding="utf-8"?>
<CM CMName="" CMPName="" CMCommercialName="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />

And my xsd

<?xml version="1.0" encoding="UTF-8"?>
<!--W3C Schema generated by XML Spy v4.4 U (http://www.xmlspy.com)-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="CM">
        <xs:complexType>
            <xs:attribute name="CMName" type="xs:string" use="required"/>
            <xs:attribute name="CMPName" type="xs:string" use="required"/>
            <xs:attribute name="CMCommercialName" type="xs:string" use="required"/>
        </xs:complexType>
    </xs:element>
</xs:schema>

Best regards
Fredrik
Avatar billede arne_v Ekspert
13. september 2006 - 18:49 #9
It works for me (in standalone J2SE context) with Xerces 2.8.0 !

What version are you on and ca you upgrade ?
Avatar billede fredand Forsker
13. september 2006 - 19:37 #10
Hello!

Thanks for your reply!

With J2SE context I guess you mean with a exploded folder structure, not packed in a jar?

I use Java 1.4_02 the Xercses I have to get back to you tomorrow.

Best regards
Fredrik
Avatar billede fredand Forsker
15. september 2006 - 21:38 #11
Hello!

I use the latest xercesIml.jar 2.8.1.

How ever I think I found out how this should be done:

parser.setProperty("http://apache.org/xml/properties/schemaSource", byteArrayInputStream );

But I run into some other problem that I have post in an other thread.

But please give a svar so I can reward you!!

Best regards
Fredrik
Avatar billede arne_v Ekspert
16. september 2006 - 01:46 #12
which was also the property I tested on because that was in the code I copy pasted from

well - they say you get blind at the eyes first

:-)

no point to me for this one

I have answered in the other thread
Avatar billede fredand Forsker
17. september 2006 - 18:10 #13
Ok!
Thanks alot!
/Fredrik
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester