问题
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.
回答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.
回答2:
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.
回答3:
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.
回答4:
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!
来源:https://stackoverflow.com/questions/25250005/can-i-validade-a-xml-file-against-xsd-fragment-in-java