【问题标题】:Can I validade a XML file against XSD fragment in Java我可以在 Java 中针对 XSD 片段验证 XML 文件吗
【发布时间】:2014-08-11 18:28:47
【问题描述】:

我可以根据 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?

非常感谢。

【问题讨论】:

  • 为什么你只想验证一个片段?模式决定了您的 XML 是否有效,因此如果 XML 标记的其余部分缺少必需的元素,如何才能认为它是有效的?我认为您可以通过分段而不是在单个文件中定义架构并针对各个部分进行验证来完成更接近您想要的事情,尽管我认为这违背了拥有架构的基本目的......
  • xsd 是专有框架的一部分,我不知道他们为什么要使用单个 xsd 来验证多个 xml。我的最后一个选择是分段定义这个 xsd。

标签: java xml jaxb xmlbeans


【解决方案1】:

不,这在 JAXB 中是不可能的,而且我不认为任何其他工具能够根据当前的 XML 模式和所示的 XML 数据进行这种部分验证。

首先,您显示的 XML 与 XML 模式 &lt;xsd:element name="tag1"...&gt;&gt; 的部分不一致。所以,无论如何它都不会验证。

其次,假设 XML Schema 代码和 XML 数据匹配,您可以考虑将 XML 数据包装到 &lt;envTeste&gt; 元素中,但由于缺少 &lt;tag&gt; 元素,验证将不会成功。

但是您可以编写一个(正确且匹配的!)元素 &lt;tag1&gt; 作为顶级 XML Schema 元素,并从 &lt;envTeste&gt; 中引用它。然后,可以解组由 &lt;tag1&gt; 组成的 XML 文档,并将 XML 模式文件传递给解组器。

另一个选择是(相当简单的)XSLT 从“有趣的”元素生成 XML 模式,将它们安装为顶级元素 - 只要模式不太复杂。不确定,但可能是可行的。

【讨论】:

  • 认为各自的xml是对的,上面只是一个例子,这不是我的问题。我真正想知道的是,我是否有可能仅使用片段进行此验证。因为 xsd 是专有的,而我通过宁静的 ws 接收它们的 xmls(也是专有的)。我不想用碎片来分隔这个 xsd,除非我别无选择。
  • 我想出了另一种选择。否则,它是包装或架构修复。
【解决方案2】:

因为我第一次误读了您的帖子,所以我删除了我的答案并创建了一个新答案:

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

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

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

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

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

【讨论】:

    【解决方案3】:

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

    在这种特殊情况下,您的本地元素声明不依赖于其他架构组件,并且不涉及名称空间,因此您可以按照其他人的建议以文本形式提取它以形成新架构。然而,在一般情况下,这将不起作用。架构的设计初衷不是按照您尝试的方式使用。

    【讨论】:

      【解决方案4】:

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

      首先我使用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
      

      构建.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) {}
      
      }
      

      谢谢大家!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-11-17
        • 2012-07-26
        • 2012-09-26
        • 2011-01-24
        • 2013-09-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多