我可以针对Java中的XSD片段验证XML文件吗?

时间:2014-08-11 18:28:47

标签: java xml jaxb xmlbeans

我可以针对xsd片段验证XML文件吗? 例如,我有一个XML:

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

和XSD一样:

<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>
............................

我想只使用片段“name = tag1”来验证我的xml。 这是可能的?使用JAXB?

非常感谢。

4 个答案:

答案 0 :(得分:1)

不,这对JAXB来说是不可能的,并且我认为任何其他工具都不能在给定当前XML Schema和XML数据的情况下进行这样的部分验证。

首先,您展示的XML不同意XML架构<xsd:element name="tag1"...>>的部分内容。所以,它无论如何都不会验证。

其次,假设匹配XML Schema代码和XML数据,您可以考虑将XML数据包装到<envTeste>元素中,但由于缺少<tag>元素,验证将无法成功。

但是你可以编写一个(正确的,匹配的!)元素<tag1>作为顶级XML Schema元素,并从<envTeste>中引用它。然后,可以将包含<tag1>的XML文档解组,并将XML模式文件传递给unmarshaller。

另一个选择是(一个相当简单的)XSLT从&#34;有趣的&#34;生成XML Schema。元素,将它们安装为顶级元素 - 如果架构不太复杂。 Iffy,但可能是可行的。

答案 1 :(得分:1)

当我第一次删除你的帖子并创建一个新的答案时,我误读了你的帖子:

如果原始模式包含要用于验证的子树,则可以通过XPath表达式(如f.e.)找到子树的顶部节点。如果您不使用命名空间定义,请//@*:name = 'tag1'//@name = 'tag1'

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

基本上,您希望以某种方式调用SchemaFactory.newSchema(Source)来生成可用于验证的架构。因此,最方便的方法是创建DOMSource

此源可以使用新的Document生成,您可以使用importNode将先前提取的子树复制到新的“模式”中。此外,您必须手动或通过从源模式复制向您正在创建的文档添加模式定义,否则您将无法获得有效的模式。

我自己还没有尝试过这种方式但是根据我过去使用这些方法的经验,我认为这可行。

答案 2 :(得分:1)

我认为你遇到的问题是模式的作者选择使tag1成为本地元素声明而不是全局元素声明。如果它是一个全局声明,你可以验证一个独立的tag1元素(人们有时会抱怨XSD的这个特性,但在你的情况下它是你想要的),但由于它是一个本地声明,它只能在上下文中访问其父envTeste元素。此外,envTeste需要存在其他同级元素,因此在验证之前不能简单地将tag1包装在envTeste中。

在这种特殊情况下,您的本地元素声明与其他模式组件没有依赖关系,并且没有涉及名称空间,因此您可以像其他人所建议的那样以文本方式提取它以形成新模式。但在一般情况下,这不起作用。该架构并非旨在按照您尝试使用它的方式使用。

答案 3 :(得分:0)

我以其他方式解决了我的问题。

首先,我使用xmlbeans创建了java对象:

ANT配置:

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>

然后我在我的项目中导入了这个jar并进行了如下验证:

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) {}

}

感谢所有人!