B4J Question Validate XML using a XSD / Json using Schema?

Discussion in 'B4J Questions' started by MathiasM, May 5, 2019.

  1. MathiasM

    MathiasM Member Licensed User

    Hello

    Is it in any way possible to validate data (XML or JSON) via a so-called Schema?
    I tried the search function for a lot of different search terms, but got no real results, so my hopes aren't very high!

    If someone knows a way how to do this, I'm very open to any insights or ti
     
  2. Erel

    Erel Administrator Staff Member Licensed User

    XmlSax library doesn't support validation.
     
  3. MathiasM

    MathiasM Member Licensed User

    Ok no problem, thanks for the fast reply!
     
  4. Daestrum

    Daestrum Well-Known Member Licensed User

    This code module code will validate xml against an xsd file
    Code:
    'Static code module
    Sub Process_Globals
     
    Private SchemaFactory As JavaObject
     
    Private factory As JavaObject
     
    Private XMLconstants As JavaObject
     
    Private Validator As JavaObject
     
    Private StreamSource As JavaObject
     
    Private xsd,xml As JavaObject
     
    Private Schema As JavaObject
    End Sub
    ' returns true for valid and false for invalid or IO error
    Sub ValidateFile(xsdFile As String,xmlFile As StringAs Boolean
     XMLconstants.InitializeStatic(
    "javax.xml.XMLConstants")
     SchemaFactory.InitializeStatic(
    "javax.xml.validation.SchemaFactory")
     factory = SchemaFactory.RunMethod(
    "newInstance",Array(XMLconstants.GetField("W3C_XML_SCHEMA_NS_URI")))
     xsd.InitializeNewInstance(
    "java.io.File",Array(xsdFile))
     xml.InitializeNewInstance(
    "java.io.File",Array(xmlFile))
     Schema = factory.RunMethod(
    "newSchema",Array(xsd))
     Validator = Schema.RunMethod(
    "newValidator",Null)
     StreamSource.InitializeNewInstance(
    "javax.xml.transform.stream.StreamSource",Array(xml))
     
    Try
      Validator.RunMethod(
    "validate",Array(StreamSource))
     
    Catch
      
    Log(LastException.Message)
      
    Return False
     
    End Try
     
    Return True 
    End Sub
    call it with (where xsd and xml are the full path names to the files) I called my module XMLValidator
    Code:
    Log(XMLValidator.ValidateFile(xsd,xml))
    If there is an error in the xml you get a log message like
    which pretty much tells you exactly what is wrong and where.

    Hope it helps.
     
  5. Daestrum

    Daestrum Well-Known Member Licensed User

    For completeness (and an example of an xsd file construct) here are the two test files I used records.xsd and records.xml
     

    Attached Files:

  6. MathiasM

    MathiasM Member Licensed User

    Very nice of you to share it with the community man! Cheers
     
  7. Daestrum

    Daestrum Well-Known Member Licensed User

    Slightly improved code module - this one will list out all the errors instead of stopping at the first one it finds.
    Code:
    'Static code module
    Sub Process_Globals
     
    Private SchemaFactory As JavaObject
     
    Private factory As JavaObject
     
    Private XMLconstants As JavaObject
     
    Private Validator As JavaObject
     
    Private StreamSource As JavaObject
     
    Private xsd,xml As JavaObject
     
    Private Schema As JavaObject
     
    Private ErrorList As List
    End Sub
    ' returns true for valid and false for invalid or IO error
    Sub ValidateFile(xsdFile As String,xmlFile As StringAs Boolean
     ErrorList.Initialize
     XMLconstants.InitializeStatic(
    "javax.xml.XMLConstants")
     SchemaFactory.InitializeStatic(
    "javax.xml.validation.SchemaFactory")
     factory = SchemaFactory.RunMethod(
    "newInstance",Array(XMLconstants.GetField("W3C_XML_SCHEMA_NS_URI")))
     xsd.InitializeNewInstance(
    "java.io.File",Array(xsdFile))
     xml.InitializeNewInstance(
    "java.io.File",Array(xmlFile))
     Schema = factory.RunMethod(
    "newSchema",Array(xsd))
     Validator = Schema.RunMethod(
    "newValidator",Null)
     StreamSource.InitializeNewInstance(
    "javax.xml.transform.stream.StreamSource",Array(xml))
     Validator.RunMethod(
    "setErrorHandler",Array(Validator.CreateEvent("org.xml.sax.ErrorHandler","xmlerr",Null)))
     Validator.RunMethod(
    "validate",Array(StreamSource))
     
     
    If ErrorList.Size > 0 Then
      
    For Each i As Object In ErrorList
       
    Log("Error "&i)
      
    Next
      
    Return False
     
    End If
     
    Return True
    End Sub
    Sub xmlerr_Event(method As String,args() As Object) As Object
     ErrorList.Add(args(
    0))
     
    Return True
    End Sub
    If you don't want the error logged twice then choose either of these code snippets to replace the 'For Each … part

    Code:
    'Technical error report
     For a = 0 To ErrorList.Size-2 Step 2
      
    Log(ErrorList.Get(a))
     
    Next
    gives this output
    Code:
    'Logical error report
     For a = 1 To ErrorList.Size-1 Step 2
      
    Log(ErrorList.Get(a))
     
    Next
    and this gives
     
    Last edited: May 9, 2019
    Kiffi likes this.
  8. avalle

    avalle Active Member Licensed User

    Anything available for JSON?
     
  9. Daestrum

    Daestrum Well-Known Member Licensed User

    The JSON is a bit harder to get working as the json.jar in the built in libraries takes preference but does not have the method toMap(…) on JSONObject so fails with a method not found exception.
    Still looking at ways round this.
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice