java - 如何生成一个类,从中我可以检索节点的 XML 作为字符串

标签 java xsd jaxb xjc maven-jaxb2-plugin

这里是从 Apache Maven 4.0.0 POM model xsd 中提取的 configuration 元素的描述.

<xs:element minOccurs="0" name="configuration">
  <xs:annotation>
    <xs:documentation source="version">0.0.0+</xs:documentation>
    <xs:documentation source="description">
      <p>The configuration as DOM object.</p> <p>By default, every element content is trimmed, but starting with Maven 3.1.0, you can add <code>xml:space="preserve"</code> to elements you want to preserve whitespace.</p> <p>You can control how child POMs inherit configuration from parent POMs by adding <code>combine.children</code> or <code>combine.self</code> attributes to the children of the configuration element:</p> <ul> <li><code>combine.children</code>: available values are <code>merge</code> (default) and <code>append</code>,</li> <li><code>combine.self</code>: available values are <code>merge</code> (default) and <code>override</code>.</li> </ul> <p>See <a href="http://maven.apache.org/pom.html#Plugins">POM Reference documentation</a> and <a href="http://plexus.codehaus.org/plexus-utils/apidocs/org/codehaus/plexus/util/xml/Xpp3DomUtils.html">Xpp3DomUtils</a> for more information.</p>
    </xs:documentation>
  </xs:annotation>
  <xs:complexType>
    <xs:sequence>
      <xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

我使用以下绑定(bind)文件从上面的 xsd 生成类:

<jxb:bindings version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
  jxb:extensionBindingPrefixes="xjc" 
  xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">

  <jxb:globalBindings>
    <!-- use plural method names for repeatable elements -->
    <xjc:simple />
  </jxb:globalBindings>

  <jxb:bindings schemaLocation="maven-4.0.0.xsd">
    <!-- rename all the node of type "any" to "elements" to improve readability -->
    <jxb:bindings multiple="true" node="//xs:any" >
      <jxb:property name="elements"/>
    </jxb:bindings>
  </jxb:bindings>
</jxb:bindings>

这很好用。例如,它生成一个 Configuration 类,该类具有返回 Element 实例的 getElements() 方法。

但是,当我遇到 configuration 标记时,我希望生成的 Configuration 类能够将所有底层元素的 XML 作为字符串保存(就像在解析器 XML 文件中写入的那样,保留注释、换行符、空行和空格。)

例如,假设我有以下 XML 文件:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>test</groupId>
  <artifactId>test</artifactId>
  <version>1.0.1-SNAPSHOT</version>
  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>${plugin.maven-compiler-plugin.version}</version>
          <configuration>
            <source>${build.jdk.source.version}</source>
              <target>${build.jdk.target.version}</target>
            <encoding>${project.build.sourceEncoding}</encoding>
                  <fork>true</fork>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

解析此 XML 文件并将其加载到生成的模型中后,我希望能够在 Configuration 实例上调用 getXML() 方法并获取:

<configuration>
  <source>${build.jdk.source.version}</source>
    <target>${build.jdk.target.version}</target>
  <encoding>${project.build.sourceEncoding}</encoding>
        <fork>true</fork>
</configuration>

(错误的缩进保持原样)

我正在考虑以下方法

  1. 在我的绑定(bind)文件中检测到我正在处理“配置”节点(如何?)
  2. 使 Configuration 类扩展一个 XmlHolder 类,能够将 XML 作为字符串保存(使用 getDom()setXml(String) 方法)
  3. 使用 XmlHolderAdapter 适配器类将 XML block 提取为字符串,并将其设置在 Configuration 类上。

我的问题:

  • 这种方法正确吗?
  • 有更好的方法吗?
  • 如何修改我的绑定(bind)文件,以及适配器类的内容应该是什么来实现此目的(如果我没记错的话,我会得到一个 XMLStreamReader 作为源)?

提前非常感谢,

最佳答案

我过去也搜索过类似问题的答案,并且需要在运行时类的相关 XSD 部分。最后我写了xjc-documentation-annotation-plugin为此。

如何一般使用它,您可能会在该答案中看到:How to make generated classes contain Javadoc from XML Schema documentation

我还为您的特定问题准备了示例和测试。请看at commit例如 gradle 项目。

为了充分理解,请逐步进行:

  1. gradle 中我使用 gradle-xjc-plugin调用XJC(您可以使用类似的maven插件或直接调用它):
plugins {
    id 'java'
    id 'org.unbroken-dome.xjc' version '1.4.1' // https://github.com/unbroken-dome/gradle-xjc-plugin
}

dependencies {
    xjcClasspath 'info.hubbitus:xjc-documentation-annotation-plugin:1.0'
    ...
}
// Results by default in `build/xjc/generated-sources`
xjcGenerate {
    /**
     * There:
     * 1. CadastralBlock.xsd is minimal example of functional.
     * 2. maven-4.0.0.xsd - example by SOq https://stackoverflow.com/questions/42223784/how-can-i-generate-a-class-from-which-i-can-retrieve-the-xml-of-a-node-as-a-stri
     */
    source = fileTree('src/main/resources') { include '*.xsd' }
    bindingFiles = fileTree('src/main/jaxb') { include '*.xjb' }
    outputDirectory = file('src/main/generated-java')
    packageLevelAnnotations = false
    targetPackage = 'info.hubbitus.xjc.plugin.example'
    extraArgs = [ '-XPluginDescriptionAnnotation' ]
}
  • 我还将生成的类添加到源路径:
  • sourceSets.main.java.srcDir new File(buildDir, xjcGenerate.outputDirectory.absolutePath)
    // If you use IntellyJ Idea:
    idea {
        module {
            // Marks the already(!) added srcDir as "generated"
            generatedSourceDirs += xjcGenerate.outputDirectory
        }
    }
    
  • 然后生成源:
  • ./gradlew xjcGenerate
    

    您的类将位于目录 src/main/generated-java 中,其中 @XsdInfo注解。对于您的情况,最感兴趣的 xsdElementPart 元素。

  • 在运行时,您只需查询并适当使用(Plugin 类包含 Configuration 作为内部类):
  •     XsdInfo xsdAnnotation = plugin.getClass().getDeclaredAnnotation(XsdInfo.class);
        System.out.println(xsdAnnotation.xsdElementPart());
    

    我准备测试TestGeneratedMavenModel充分展示它。

    关于java - 如何生成一个类,从中我可以检索节点的 XML 作为字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42223784/

    相关文章:

    java - 将java对象转换为XML?

    java - 如何让 CXF 理解 Map<String, <List<MyBean>>?

    java - 以编程方式构建约束布局

    java - 了解层次结构方法调用

    xml - 解码错误 : unexpected element (uri :"", 本地 :"user")。预期元素是(无)

    xsd - 对 xml 模式中的元素同时具有属性和限制

    java - 使用 selenium 抓取 td 属性行

    java - 与类(Class)斗争,延伸和实现

    xml - Spring Security XML 错误 - cvc-complex-type.2.4.a : Invalid content was found starting with element 'csrf'

    java - 使用 JAXB 编码(marshal)通用对象时如何摆脱命名空间