dtd文件的JAXB绑定模式

时间:2013-09-06 22:12:47

标签: jaxb dtd

一个noobie问题。我正在从dtd文件(USPTO dtd)生成Java代码。 DTD指定根元素如下:

<!ELEMENT us-patent-grant (doc-page+ | (us-bibliographic-data-grant , abstract* , drawings? , description , us-sequence-list-doc? , us-megatable-doc?,table-external-doc* , us-chemistry* , us-math* ,us-claim-statement , claims))>

当我使用以下绑定模式运行xjc时

    <?xml version="1.0"?>
    <xml-java-binding-schema version="1.0ea2">
       <element name="us-patent-grant" type="class" root="true"></element>
    </xml-java-binding-schema>

我看到生成了以下Java对象

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "docPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims"
    })
    @XmlRootElement(name = "us-patent-grant")
    public class UsPatentGrant {
       ....

    @XmlElements({
        @XmlElement(name = "doc-page", required = true, type = DocPage.class),
        @XmlElement(name = "us-bibliographic-data-grant", required = true, type = UsBibliographicDataGrant.class),
        @XmlElement(name = "abstract", required = true, type = Abstract.class),
        @XmlElement(name = "drawings", required = true, type = Drawings.class),
        @XmlElement(name = "description", required = true, type = Description.class),
        @XmlElement(name = "us-sequence-list-doc", required = true, type = UsSequenceListDoc.class),
        @XmlElement(name = "us-megatable-doc", required = true, type = UsMegatableDoc.class),
        @XmlElement(name = "table-external-doc", required = true, type = TableExternalDoc.class),
        @XmlElement(name = "us-chemistry", required = true, type = UsChemistry.class),
        @XmlElement(name = "us-math", required = true, type = UsMath.class),
        @XmlElement(name = "us-claim-statement", required = true, type = UsClaimStatement.class),
        @XmlElement(name = "claims", required = true, type = Claims.class)
    })
    protected List<Object> docPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims;

     .........

public List<Object> getDocPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims() {
    if (docPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims == null) {
        docPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims = new ArrayList<Object>();
    }
    return this.docPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims;
}

所以我的问题是如何更改长吸气剂的名称

getDocPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims

在绑定模式中?

提前谢谢你。

2 个答案:

答案 0 :(得分:2)

这不是一个答案,而是你怀疑的证据。

com.sun.tools.xjc.reader.dtd.Element的{​​{3}}来源中,在JAXB/XJC方法中,您可以看到此摘录,遍历elements的子Element

if(b.isRepeated || b.elements.size()>1) {
    // collection
    StringBuilder name = new StringBuilder();
    for( Element e : b.elements ) {
        if(name.length()>0)
            name.append("Or");
        name.append(owner.model.getNameConverter().toPropertyName(e.name));
    }
    ...
} else {
    // single property
    String name = b.elements.iterator().next().name;
            String propName = owner.model.getNameConverter().toPropertyName(name);
            ...
}

看起来它几乎没有机会改变有多个子元素的"Or"分隔符的序列。

您可以在bindInfo的其他地方看到Element允许自定义名称,但不在此附近。除非别人能够发现它,否则重命名的可能性似乎就此结束。简而言之,CElementPropertyInfo此输出会导致BeanGenerator.fields,导致JDefinedClass.fields,然后由JDefinedClass.declareBody()直接输出。

正如bind()所说,DTD支持仍然是试验性的......

答案 1 :(得分:1)

正如@ df778899所提到的那样,如果您查看下面的源代码,那么就无法做到这一点

CElementPropertyInfo p;
if(b.isRepeated || b.elements.size()>1) {
    // collection
    StringBuilder name = new StringBuilder();
    for( Element e : b.elements ) {
        if(name.length()>0)
            name.append("Or");
        name.append(owner.model.getNameConverter().toPropertyName(e.name));
    }
    p = new CElementPropertyInfo(name.toString(), REPEATED_ELEMENT, ID.NONE, null, null,null/*TODO*/, locator, !b.isOptional );
    for( Element e : b.elements ) {
        CClassInfo child = owner.getOrCreateElement(e.name).getClassInfo();
        assert child!=null; // we are requiring them to be classes.
        p.getTypes().add(new CTypeRef(child,new QName("",e.name),null,false,null));
    }

CElementPropertyInfo对象采用名称,唯一的修复方法是使用检测。所以我创建了一个maven项目

<强>的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>org.tarunlalwani</groupId>
    <artifactId>jxc-customizer</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
            <!-- https://mvnrepository.com/artifact/javassist/javassist -->
        <!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
            <dependency>
                <groupId>org.javassist</groupId>
                <artifactId>javassist</artifactId>
                <version>3.22.0-GA</version>
            </dependency>
        </dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>
                            ${project.build.directory}/libs
                        </outputDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifestEntries>
                        <Premain-Class>com.xjc.javaagent.SimpleAgent</Premain-Class>
                        <Boot-Class-Path>libs/javassist-3.22.0-GA.jar</Boot-Class-Path>
                        <Class-Path>libs/javassist-3.22.0-GA.jar</Class-Path>
                    </manifestEntries>
                    <manifest>
                        <classpathPrefix>libs/</classpathPrefix>

                    </manifest>
                </archive>
            </configuration>
        </plugin>

    </plugins>
</build>

</project>

<强> jxccustomizer / SRC /主/ JAVA / COM / XJC / javaagent / SimpleAgent.java

package com.xjc.javaagent;

import java.lang.instrument.Instrumentation;

public class SimpleAgent {

    public static void premain(String agentArgs,
                               Instrumentation instrumentation){

        System.out.println("Starting Agent");
        SimpleClassFileTransformer transformer =
                new SimpleClassFileTransformer();
        instrumentation.addTransformer(transformer);
    }
}

<强> jxccustomizer / SRC /主/ JAVA / COM / XJC / javaagent / SimpleClassFileTransformer.java

package com.xjc.javaagent;

import javassist.*;

import java.io.ByteArrayInputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

public class SimpleClassFileTransformer implements
        ClassFileTransformer {

    public byte[] transform(ClassLoader loader,
                            String className, Class classBeingRedefined,
                            ProtectionDomain protectionDomain, byte[] classfileBuffer)
            throws IllegalClassFormatException {

        byte[] byteCode = classfileBuffer;
        if (className.endsWith("/CPropertyInfo")) {
            System.out.println("Loading class - " + className);
            try {
                ClassPool classPool = ClassPool.getDefault();
                CtClass ctClass = classPool.makeClass(
                        new ByteArrayInputStream(classfileBuffer));
                CtConstructor[] constructors = ctClass.getConstructors();
                for (CtConstructor c : constructors) {
                    c.insertBefore("{        String propFile = System.getProperty(\"XJC_REMAP\");\n" +
                            "        if (propFile != null)\n" +
                            "        {\n" +
                            "            System.out.println(\"External remap file provided\");\n" +
                            "            java.util.Properties props = new java.util.Properties();\n" +
                            "            try {\n" +
                            "                props.load(new java.io.FileInputStream(propFile));\n" +
                            "                java.util.Enumeration enums = props.propertyNames();\n" +
                            "                while (enums.hasMoreElements()) {\n" +
                            "                    String key = (String)enums.nextElement();\n" +
                            "                    String value = props.getProperty(key);\n" +
                            "                    try {\n" +
                            "                        System.out.println(\"Checking if \" + name + \" matches \" + key);\n" +
                            "                        java.util.regex.Pattern pat = java.util.regex.Pattern.compile(\"^\" + key +\"$\", java.util.regex.Pattern.CASE_INSENSITIVE);\n" +
                            "                        if (pat.matcher(name).find())\n" +
                            "                        {\n" +
                            "                            System.out.println(\"Replacing \" + name + \" with \" + value);\n" +
                            "                            name = value;\n" +
                            "                            break;\n" +
                            "                        }\n" +
                            "                    } finally {\n" +
                            "                        if (name == key) {\n" +
                            "                            System.out.println(\"Replacing \" + name + \" with \" + value);\n" +
                            "                            name = value;\n" +
                            "                        }\n" +
                            "                        break;\n" +
                            "                    }\n" +
                            "                }\n" +
                            "            } catch (java.io.IOException e) {\n" +
                            "                e.printStackTrace();\n" +
                            "            }\n" +
                            "        }}");
                }
                byteCode = ctClass.toBytecode();
                ctClass.detach();
                System.out.println("NO Exception occured");
            } catch (Throwable e) {
                System.out.println("Exception occurred");
                e.printStackTrace();
            }
        }

        return byteCode;
    }
}

上述类可以加载-DXJC_REMAP=<filepath>指定的属性文件,该文件格式低于

<强> remap.properties

docPageOr.*=patentDocument

现在测试解决方案。首先需要通过运行以下命令

为代理生成jar
mvn clean package

接下来是创建一些测试dtd

<强> binding.xjb

<?xml version="1.0"?>
<xml-java-binding-schema>
    <options package="org"/>
    <element name="us-patent-grant" type="class" root="true"></element>
</xml-java-binding-schema>

<强> testing.dtd

<?xml version="1.0" encoding="utf-8"?>
 <!-- DTD to write simple stories
      Made by Daniel K. Schneider / TECFA / University of Geneva
      VERSION 1.0
      30/10/2003 -->
<!ELEMENT us-patent-grant (doc-page+ | (us-bibliographic-data-grant , abstract* , drawings? , description , us-sequence-list-doc? , us-megatable-doc?,table-external-doc* , us-chemistry* , us-math* ,us-claim-statement , claims))>

现在使用它来运行具有xjc

的代理
$ export _JAVA_OPTIONS="-javaagent:/Users/tarun.lalwani/Desktop/tarunlalwani.com/tarunlalwani/workshop/ub16/so/jaxb/jxccustomizer/target/jxc-customizer-1.0-SNAPSHOT.jar -DXJC_REMAP=/Users/tarun.lalwani/Desktop/tarunlalwani.com/tarunlalwani/workshop/ub16/so/jaxb/remap.properties"

$ xjc -b binding.xjb -dtd testing.dtd
Picked up _JAVA_OPTIONS: -javaagent:/Users/tarun.lalwani/Desktop/tarunlalwani.com/tarunlalwani/workshop/ub16/so/jaxb/jxccustomizer/target/jxc-customizer-1.0-SNAPSHOT.jar -DXJC_REMAP=/Users/tarun.lalwani/Desktop/tarunlalwani.com/tarunlalwani/workshop/ub16/so/jaxb/remap.properties
objc[33035]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/bin/xjc (0x10ed964c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10eded4e0). One of the two will be used. Which one is undefined.
Starting Agent
Loading class 2 - com/sun/tools/internal/xjc/model/CPropertyInfo
inside try
Updating cons 1
Updating cons
NO Exception occured
parsing a schema...
External remap file provided
Checking if DocPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims matches docPageOr.*
Replacing DocPageOrUsBibliographicDataGrantOrAbstractOrDrawingsOrDescriptionOrUsSequenceListDocOrUsMegatableDocOrTableExternalDocOrUsChemistryOrUsMathOrUsClaimStatementOrClaims with patentDocument
compiling a schema...
org/Abstract.java
org/Claims.java
org/Description.java
org/DocPage.java
org/Drawings.java
org/ObjectFactory.java
org/TableExternalDoc.java
org/UsBibliographicDataGrant.java
org/UsChemistry.java
org/UsClaimStatement.java
org/UsMath.java
org/UsMegatableDoc.java
org/UsPatentGrant.java
org/UsSequenceListDoc.java

现在生成的文件内容符合要求

Correct generated output

以上代码的git repo可在以下链接中找到

https://github.com/tarunlalwani/xjc-java-agent-customization