0

Can I validate a XML file against a xsd fragment? For example, I have a XML like:

<tag1>
    <xx>...</xx>
</tag1>

And a XSD like:

<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="envTeste">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="tag" minOccurs="1" maxOccurs="1">
          <xsd:simpleType>
            <xsd:restriction base="xsd:int">
              <xsd:totalDigits value="1" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>
        <xsd:element name="tag1" minOccurs="1" maxOccurs="1">
          <xsd:simpleType>
            <xsd:restriction base="xsd:string">
              <xsd:pattern value="^\d{1,15}$"/>
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>
............................

I want to use just the fragment "name=tag1" to validade my xml. It's possible? Using JAXB?

Thanks a lot.

fdam
  • 820
  • 1
  • 11
  • 25
  • 1
    Why would you want to only validate a fragment? The schema is what determines that your XML is valid, so if the rest of the XML markup is missing required elements, how can it be considered valid? I would think you could accomplish something closer to what you want by defining the schema in pieces rather than in a single file and validating against the individual pieces, though I think this defeats the fundamental purpose of having a schema... – Ryan J Aug 11 '14 at 18:33
  • The xsd is part of a proprietary framework, and I have no idea why they do a single xsd to validate several xml. My last option is define this xsd in pieces. – fdam Aug 11 '14 at 18:59

4 Answers4

1

No, this is not possible with JAXB, and I don't think any other tool would be able to do such partial validations given the current XML Schema and the XML data as shown.

First, the XML you've shown disagrees with the part of the XML schema <xsd:element name="tag1"...>>. So, it won't validate anyway.

Second, assuming matching XML Schema code and XML data, you could consider wrapping the XML data into an <envTeste> element, but then validation would not succeed due to the missing <tag> element.

BUT you can write a (correct and matching!) element <tag1> as a top-level XML Schema element and references it from within <envTeste>. Then, an XML document consisting of a <tag1> could be unmarshalled with the XML schema file being passed to the unmarshaller.

Another option would be a (rather simple) XSLT to generate an XML Schema from the "interesting" elements, installing them as top level elements - provided the schema isn't too intricate. Iffy, but could be viable.

laune
  • 31,114
  • 3
  • 29
  • 42
  • Consider that the respective xml is right, above is just an example, this is not my problem. What I wanna really know, is whether it's possible or not I do this validation just using a fragment. Because the xsd is proprietary, and the xmls I'm receiving them through a restful ws (proprietary too). I don't want to separate this xsd by fragments, only if I have no option. – fdam Aug 11 '14 at 18:54
  • I've thought up another alternative. Otherwise, it's the wrapping or the Schema fix. – laune Aug 11 '14 at 19:24
1

As I've misread your post the first time I've deleted my answer and created a new one:

If the original schema contains a subtree you want to use for validation you could find the top-node of the subtree via an XPath expression like f.e. //@*:name = 'tag1' or //@name = 'tag1' if you don't use namespace definitions.

Node node = (Node)xpath.evaluate(xpathExpression, originSchemaDocument, XPathConstants.NODE);

Basically you want to invoke SchemaFactory.newSchema(Source) in some way to generate the schema you can use for validation. Therefore probably the most convenient way is to create a DOMSource.

This source can furthermore be generated using a new Document where you can probably use importNode to copy the previously extracted sub-tree into the new "schema". You furthermore have to add a schema definition to the document you are creating either manually or by copying from the source schema else you wont get a valid schema.

I haven't tried it this way myself yet but from my past experience with those methods I think this could work.

Roman Vottner
  • 12,213
  • 5
  • 46
  • 63
1

I think the problem you are having is that the authors of the schema chose to make tag1 a local element declaration rather than a global element declaration. If it were a global declaration, you could validate a free-standing tag1 element (people sometimes complain about this feature of XSD, but in your case it's what you want), but since its a local declaration, it is only accessible in the context of its parent envTeste element. Moreover, the envTeste requires other sibling elements to be present, so you can't simply wrap your tag1 in an envTeste prior to validation.

In this particular case your local element declaration has no dependencies on other schema components, and there are no namespaces involved so you could extract it textually to form a new schema as others have suggested. In the general case however this will not work. The schema wasn't designed to be used the way you are trying to use it.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
0

I solved my problem in other way.

First I created java objects using xmlbeans:

ANT config:

build.properties

xbean-dest-file = ./lib/sat-beans-1.0.jar # my generated jar
xbean-class-name = org.apache.xmlbeans.impl.tool.XMLBean
xbean-class-path = ./lib/xbean.jar:./lib/jsr173_1.0_api.jar #dependencies

build.xml

<target name="sat-beans">
    <mkdir  dir="${xbean-gen}"/>
    <mkdir  dir="${xbean-classes}"/>
    <taskdef name="xmlbean" classname="${xbean-class-name}" classpath="${xbean-class-path}"/>
    <xmlbean schema="./xsd/CfeTeste_0006.xsd" classgendir="${xbean-classes}" 
            srcgendir="${xbean-gen}"  
            destfile="${xbean-dest-file}" 
            classpath="${xbean-class-path}" />
</target>

Then I imported this jar in my project and did the validation like:

public void validate(String xml) {

    try {

        List<XmlValidationError> errors = new ArrayList<XmlValidationError>();
        EnvTesteDocument envTesteDocument = EnvTesteDocument.Factory.parse(xml);

        XmlOptions voptions = new XmlOptions();
        voptions.setValidateOnSet();
        voptions.setErrorListener(errors);

        if (envTesteDocument.getEnvTeste().getCFe().validate(voptions)) {
            return;
        }

        for (XmlValidationError error : errors) {
            ...
        }


    } catch (XMLInvalidException e) {}

}

thanks for all!

fdam
  • 820
  • 1
  • 11
  • 25