java - JAXB如何动态生成模式以立即使用它进行验证?

标签 java xml validation jaxb xsd

我花了很长时间试图弄清楚如何验证 XML 文件,并且我已经让它与预先生成的 XSD 架构一起使用。但是,我希望在不创建文件的情况下动态生成模式,根据我指定的注释类,我尝试不向 SchemaFactory 指定任何参数,但似乎只是创建一个空模式(请参阅下面的评论) .

以下是我用于 JAXB 读取和写入 XML 文件的两个类。

这是 XMLTranslationWrapper 类的代码:

@XmlAccessorType(XmlAccessType.FIELD)

@XmlRootElement(namespace = "my.package.namespace")
public class XMLTranslationWrapper {

      @XmlElementWrapper(name   = "TRANSLATIONS")
      @XmlElement(name          = "TRANSL")
      public ArrayList<XMLTranslationNode> translations;

      public XMLTranslationWrapper(){
          translations = new ArrayList<XMLTranslationNode>();
      }

      public void setTranslations(ArrayList<XMLTranslationNode> translations){
          this.translations = translations;
      }

      public XMLTranslationNode getTranslation(String code){
          for(XMLTranslationNode transl : translations){
              if(transl.getCode().equals(code))
                  return transl;
          }
        return null;
      }

      public void addTranslation(XMLTranslationNode translation){
          this.translations.add(translation);
      }
}

这是 XMLTranslationNode 类的代码:

@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlRootElement(name = "TRANSL")

@XmlType(propOrder = { "severity", "translation" })
public class XMLTranslationNode {

    private String severity;

    private String code;
    private String translation;

    @XmlElement(name="SEVERITY")
    public String getSeverity(){
        return this.severity;
    }

    public void setSeverity(String severity){
        this.severity = severity;
    }

    @XmlAttribute(name="CODE")
    public String getCode(){
        return this.code;
    }

    public void setCode(String code){
        this.code = code;
    }

    @XmlElement(name="TRANSLATION")
    public String getTranslation(){
        return this.translation;
    }

    public void setTranslation(String translation){
        this.translation = translation;
    }

}

这是我用来生成预生成的 XSD 架构的代码:

public class generateSchema {

    public static void main(String[] args) {
        JAXBContext jaxbContext;
        try {
            jaxbContext = JAXBContext.newInstance(XMLTranslationWrapper.class);
            SchemaOutputResolver sor = new MySchemaOutputResolver();
            jaxbContext.generateSchema(sor);
        } catch (JAXBException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class MySchemaOutputResolver extends SchemaOutputResolver {

        public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException {
            File file = new File(suggestedFileName);
            StreamResult result = new StreamResult(file);
            System.out.println(file.toURI().toURL().toString());
            result.setSystemId(file.toURI().toURL().toString());
            return result;
        }

    }

}

最后这是一个可用于测试代码的示例 XML:

<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
<ns2:xmlTranslationWrapper xmlns:ns2="my.package.namespace">
    <TRANSLATIONS>
        <TRANSL CODE="123">
            <SEVERITY>Information</SEVERITY>
            <TRANSLATION>ABC</TRANSLATION>
        </TRANSL>
    </TRANSLATIONS>
</ns2:xmlTranslationWrapper>

如何动态生成 XSD 架构,而不创建相当于使用预生成的 XSD 架构的文件?

最佳答案

正如所 promise 的那样。这个想法很简单:

  • 首先将架构生成为 DOM 结果
  • 从生成的 DOM 中解析它
  • 最后,用于验证

我认为你不能做得比这更好。 JAXB 的 schemagen 内部结构似乎与 javax.xml.validation.Schema 不兼容。所以创建 DOM 然后解析它是最简单的方法。

Code example :

public class DynamicSchemaTest {

    @XmlRootElement
    public static class A {
        @XmlAttribute(required = true)
        public String name;

        public A() {
        }

        public A(String name) {
            this.name = name;
        }
    }

    @Test(expected = MarshalException.class)
    public void generatesAndUsesSchema() throws JAXBException, IOException,
            SAXException {
        final JAXBContext context = JAXBContext.newInstance(A.class);
        final DOMResult result = new DOMResult();
        result.setSystemId("schema.xsd");
        context.generateSchema(new SchemaOutputResolver() {
            @Override
            public Result createOutput(String namespaceUri,
                    String suggestedFileName) {
                return result;
            }
        });

        @SuppressWarnings("deprecation")
        final SchemaFactory schemaFactory = SchemaFactory
                .newInstance(WellKnownNamespace.XML_SCHEMA);
        final Schema schema = schemaFactory.newSchema(new DOMSource(result
                .getNode()));

        final Marshaller marshaller = context.createMarshaller();
        marshaller.setSchema(schema);
        // Works
        marshaller.marshal(new A("works"), System.out);
        // Fails
        marshaller.marshal(new A(null), System.out);
    }
}

关于java - JAXB如何动态生成模式以立即使用它进行验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26192967/

相关文章:

c# - 我如何告诉数据注释验证器也验证复杂的子属性?

java - 传入一个嵌入java类的对象作为参数

java - 如何管理屏幕

java - 如何为 main 方法编写 Junit,将 "Hello, World!"字符串打印到控制台并使用 Spring 框架

java - Android 应用程序因 imageview 崩溃

java - 如何使用 xsd 限制 xml 文件中的 ENTITY 标记

java - 将树作为子树添加到不同类型的树

xml - Go 中的低级 XML 流编写器?

c# - 什么是过时的 XmlValidatingReader 类的良好替代品?

c# - 我将如何验证从 List<T> 派生的类中的添加?