简体   繁体   English

在maven-jaxb2-plugin中插入自定义setter

[英]Insert custom setter in maven-jaxb2-plugin

I'm using the org.jvnet.jaxb2.maven2:maven-jaxb2-plugin to create POJOs from XSD schema files. 我正在使用org.jvnet.jaxb2.maven2:maven-jaxb2-plugin从XSD架构文件创建POJO。

Now I want to insert something like a custom setter. 现在我想插入类似自定义setter的东西。 It should trim all Strings and should remove certain characters. 它应修剪所有字符串,并应删除某些字符。

Do you know how to do this? 你知道怎么做吗?


The XJB file: XJB文件:

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings version="2.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
    <jaxb:bindings schemaLocation="my-schema-xml4.xsd" node="/xs:schema">
        <xjc:javaType name="java.lang.String" adapter="my.StringAdapter" />
    </jaxb:bindings>
</jaxb:bindings>

Solution for binding Java types: 绑定Java类型的解决方案:

<?xml version="1.0" encoding="UTF-8" ?>
<bindings version="2.0" xmlns="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
    <bindings schemaLocation="mySchema-xml4.xsd" node="/xs:schema">
        <globalBindings>
            <xjc:javaType name="java.lang.String" xmlType="xs:string"
                adapter="com.name.MyAdapter" />
                    <xjc:javaType name="java.lang.String" xmlType="xs:anySimpleType"
                adapter="com.name.MyAdapter" />
        </globalBindings>
    </bindings>
</bindings>

But the @XmlJavaTypeAdapter still isn't added to the content property in nodes with mixed content, although the property has the type java.lang.String . 但是@XmlJavaTypeAdapter仍然没有添加到具有混合内容的节点中的content属性,尽管该属性的类型为java.lang.String

I think the best way to achieve this is to implement an own XmlAdapter and configure it via the property customization. 我认为实现这一目标的最佳方法是实现自己的XmlAdapter并通过属性自定义进行配置。 You can do this with a standard jaxb:property customization or with the annotate plugin . 您可以使用标准的jaxb:property自定义或使用annotate插件执行此操作

jaxb:property : jaxb:property

  <jaxb:property>
    <jaxb:baseType>
      <xjc:javaType name="java.lang.String"
        adapter="com.acme.foo.MyAdapter"/>
    </jaxb:baseType>
  </jaxb:property>

Annotate plugin: 注释插件:

  <annox:annotate target="field">
    <annox:annotate
      annox:class="javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter"
      value="com.acme.foo.MyAdapter"/>
  </annox:annotate>

See the sample project here: 请在此处查看示例项目:

https://svn.java.net/svn/jaxb2-commons~svn/basics/trunk/tests/one/ https://svn.java.net/svn/jaxb2-commons~svn/basics/trunk/tests/one/

If your XSD will not change in the future just generate the POJOs, comment out the JAXB plugin and modify the source by hand. 如果您的XSD将来不会更改,只需生成POJO,注释掉JAXB插件并手动修改源代码。

If your XSD changes rarely you still can use this solution with a version control system. 如果您的XSD 很少更改,您仍然可以将此解决方案与版本控制系统一起使用。 Commit the generated source, modify the POJOs and commit the modifications. 提交生成的源,修改POJO并提交修改。 Next time when the XSD is modified generate a patch between the two commits, generate the POJOs from the new XSD and apply the patch. 下次修改XSD时,在两次提交之间生成补丁,从新的XSD生成POJO并应用补丁。 I found this solution a lot simpler in cases where the XSD almost never changes. 在XSD几乎从不改变的情况下,我发现这个解决方案更简单。

An alternate approach would be to use a StAX StreamReaderDelegate to manipulate the XML text before it was received by the JAXB implementation. 另一种方法是使用StAX StreamReaderDelegate在JAXB实现接收XML文本之前对其进行操作。

Demo 演示

Your code would look something like the following. 您的代码看起来如下所示。 You would implement a StreamReaderDelegate to manipulate the text returned from the text events: 您将实现StreamReaderDelegate来操作从文本事件返回的文本:

package forum7329881;

import java.io.FileInputStream;
import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.stream.util.StreamReaderDelegate;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Customer.class);

        XMLInputFactory xif = XMLInputFactory.newInstance();
        XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("src/forum7329881/input.xml"));
        xsr = new MyStreamReaderDelegate(xsr);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Customer customer = (Customer) unmarshaller.unmarshal(xsr);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(customer, System.out);
    }

    private static class MyStreamReaderDelegate extends StreamReaderDelegate {

        public MyStreamReaderDelegate(XMLStreamReader xsr) {
            super(xsr);
        }


        @Override
        public String getText() {
            return super.getText().trim();
        }

        @Override
        public char[] getTextCharacters() {
            return getText().toCharArray();
        }

        @Override
        public int getTextLength() {
            return getText().length();
        }

        @Override
        public int getTextStart() {
            return 0;
        }

    }

}

input.xml input.xml中

Below is sample input that contains whitespace in the text nodes: 下面是包含文本节点中的空格的示例输入:

<customer Id="1">
    <name>    Jane Doe    </name>
    <address>
        <street>    123 A Street    </street>
    </address>
</customer>

Output 产量

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer>
    <address>
        <street>123 A Street A</street>
    </address>
    <name>Jane Doe</name>
</customer>

Customer 顾客

package forum7329881;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Customer {

    private String name;
    private Address address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

}

Address 地址

package forum7329881;

public class Address {

    private String street;

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

}

For More Information 欲获得更多信息

Below is a link to a more detailed example where I used a StAX StreamReaderDelegate to support case insensitive unmarshalling: 下面是一个更详细的示例的链接,其中我使用StAX StreamReaderDelegate来支持不区分大小写的解组:

In my opinion, you should use AOP, Pick Spring AOP, for instance, Intercept the Adapter methods to have trim / strip logic. 在我看来,你应该使用AOP,Pick Spring AOP,例如Intercept the Adapter方法来修剪/剥离逻辑。 In fact this can now be a generic logic that would apply to all string types. 实际上,现在这可以是适用于所有字符串类型的通用逻辑。 If this sounds convincing, I can further help with the code 如果这听起来令人信服,我可以进一步帮助代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM