首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JAXB将非ASCII字符转换为ASCII字符。

JAXB将非ASCII字符转换为ASCII字符。
EN

Stack Overflow用户
提问于 2014-02-06 14:56:16
回答 1查看 2.8K关注 0票数 6

我有一些xsd模式,元素名包含非ASCII字符。当我使用生成JAXB类命令使用Eclipse生成java类时,生成的类和变量包含非ASCII字符。我想将这个非ASCII字符转换为ASCII字符。

我已经在JAVA_TOOL_OPTIONS设置了区域设置

代码语言:javascript
复制
-Duser.country=GB -Duser.language=en

例如

代码语言:javascript
复制
İ -> I
Ç -> C
Ş -> S
Ö -> O
Ğ -> G
Ü -> U
ı -> i
ö -> o
ü -> u
ç -> c
ğ -> g
ş -> s
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-02-14 12:55:35

编辑:,因为需求是通用的解决方案,并且不使用外部绑定文件__,所以我在下面提供了2选项:

选项1--通用解决方案--创建自定义XJC插件以实现规范化

通用解决方案是有效的:

  1. 扩展com.sun.tools.xjc.Plugin抽象类并重写JAXB用于命名工件的方法--基本创建插件
  2. 在jar中的jar文件夹的services目录中专门调用实现的名称后,将此实现打包到META-INF
  3. 将这个新创建的jar与jaxb库一起部署,并通过ANT运行它(下面提供了build.xml,请继续阅读)

为了您的目的,我创建了一个插件,您可以从https://www.dropbox.com/s/1igbqhjdup5niki/normalizeplugin_xjc_v0.4.jar下载jar,从https://www.dropbox.com/s/orjr94l5pnn5il6/build.xml下载ant脚本https://www.dropbox.com/s/orjr94l5pnn5il6/build.xml。将jar放到eclipse中的构建路径,并编辑ant文件,以提供JAXB库的位置、生成类的目标包、项目名称和模式位置,并运行它。就这样!

Explanation:

我创建了一个带有额外命令行选项-normalize的定制-normalize插件,用它们的ASCII等价物替换您创建的Java类、方法、变量、属性和接口中的重音字符。

XJC具有自定义插件创建功能,可以控制生成的类、变量等的名称、注释和其他属性。这篇博客文章虽然老了,但它可以让您开始了解这些插件实现的基础知识。

长话短说,我创建了一个扩展抽象com.sun.tools.xjc.Plugin类的类,将其方法重写为onActivated

在此方法中,我将com.sun.tools.xjc.Option#setNameConverter设置为一个自定义类,该类负责覆盖获取类、方法等名称所需的方法。我还将源代码提交给我的git回购这里,下面是它的详细用法:

代码语言:javascript
复制
import java.text.Normalizer;

import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;

import com.sun.tools.xjc.BadCommandLineException;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.Plugin;
import com.sun.tools.xjc.outline.Outline;
import com.sun.xml.bind.api.impl.NameConverter;

/**
 * {@link Plugin} that normalized the names of JAXB generated artifacts
 * 
 * @author popofibo
 */
public class NormalizeElements extends Plugin {

    /**
     * Set the command line option
     */
    @Override
    public String getOptionName() {
        return "normalize";
    }

    /**
     * Usage content of the option
     */
    @Override
    public String getUsage() {
        return "  -normalize    :  normalize the classes and method names generated by removing the accented characters";
    }

    /**
     * Set the name converted option to a delegated custom implementation of
     * NameConverter.Standard
     */
    @Override
    public void onActivated(Options opts) throws BadCommandLineException {
        opts.setNameConverter(new NonAsciiConverter(), this);
    }

    /**
     * Always return true
     */
    @Override
    public boolean run(Outline model, Options opt, ErrorHandler errorHandler)
            throws SAXException {
        return true;
    }

}

/**
 * 
 * @author popofibo
 * 
 */
class NonAsciiConverter extends NameConverter.Standard {

    /**
     * Override the generated class name
     */
    @Override
    public String toClassName(String s) {
        String origStr = super.toClassName(s);
        return normalize(origStr);
    }

    /**
     * Override the generated property name
     */
    @Override
    public String toPropertyName(String s) {
        String origStr = super.toPropertyName(s);
        return normalize(origStr);
    }

    /**
     * Override the generated variable name
     */
    @Override
    public String toVariableName(String s) {
        String origStr = super.toVariableName(s);
        return normalize(origStr);
    }

    /**
     * Override the generated interface name
     */
    @Override
    public String toInterfaceName(String s) {
        String origStr = super.toInterfaceName(s);
        return normalize(origStr);
    }

    /**
     * Match the accented characters within a String choosing Canonical
     * Decomposition option of the Normalizer, regex replaceAll using non POSIX
     * character classes for ASCII
     * 
     * @param accented
     * @return normalized String
     */
    private String normalize(String accented) {
        String normalized = Normalizer.normalize(accented, Normalizer.Form.NFD);
        normalized = normalized.replaceAll("[^\\p{ASCII}]", "");
        return normalized;
    }
}

要使用正常的jaxb解编组来启用这个插件,需要将这些类打包到jar中,在jar中添加/META-INF/services/com.sun.tools.xjc.Plugin文件并将其放在构建路径中。

jar中的/META-INF/services/com.sun.tools.xjc.Plugin文件:

该文件内容如下:

代码语言:javascript
复制
com.popofibo.plugins.jaxb.NormalizeElements

如前所述,我将其打包到一个jar中,并将其部署到eclipse构建路径中,现在我在运行eclipse kepler with JDK 1.7时遇到的问题是我得到了这个异常(消息):

代码语言:javascript
复制
com.sun.tools.xjc.plugin Provider <my class> not a subtype

因此,最好使用ANT生成类,下面的build.xml对迄今所做的工作进行了公正的处理:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<project name="SomeProject" default="createClasses">

    <taskdef name="xjc" classname="com.sun.tools.xjc.XJC2Task">
        <classpath>
            <pathelement
                path="C:/Workspace/jaxb-ri-2.2.7/jaxb-ri-2.2.7/lib/jaxb-xjc.jar" />
            <pathelement
                path="C:/Workspace/jaxb-ri-2.2.7/jaxb-ri-2.2.7/lib/jaxb-impl.jar" />
            <pathelement
                path="C:/Workspace/jaxb-ri-2.2.7/jaxb-ri-2.2.7/lib/jaxb2-value-constructor.jar" />
            <pathelement path="C:/Workspace/normalizeplugin_xjc_v0.4.jar" />
        </classpath>
    </taskdef>

    <target name="clean">
        <delete dir="src/com/popofibo/jaxb" />
    </target>

    <target name="createClasses" depends="clean">
        <xjc schema="res/some.xsd" destdir="src" package="com.popofibo.jaxb"
            encoding="UTF-8">
            <arg value="-normalize" />
        </xjc>
    </target>
</project>

展示我选择的这个规范化过程的模式是:

代码语言:javascript
复制
<xs:element name="shiporder">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="Örderperson" type="xs:string"/>
      <xs:element name="Şhİpto">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="address" type="xs:string"/>
            <xs:element name="Çity" type="xs:string"/>
            <xs:element name="ÇoÜntry" type="xs:string"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="İtem" maxOccurs="unbounded">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="title" type="xs:string"/>
            <xs:element name="note" type="xs:string" minOccurs="0"/>
            <xs:element name="qÜantity" type="xs:positiveInteger"/>
            <xs:element name="price" type="xs:decimal"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
    <xs:attribute name="orderid" type="xs:string" use="required"/>
  </xs:complexType>
</xs:element>

</xs:schema> 

如您所见,我已经设置了参数和包,以说明我希望在哪里生成类,以及生成的工件中的类、方法、变量的ASCII名称(我看到的唯一差距是XML注释,它不会影响原因,但也很容易克服):

上面的屏幕截图显示了名称已经标准化,并被它们的ASCII对应物所取代(为了检查它在没有替换的情况下看起来如何,请参考选项2中的屏幕快照)。

选项2-使用外部绑定文件

若要删除重音字符,可以创建自定义绑定文件,并在生成类时使用该文件绑定类名和属性名称。参见:使用JAXB绑定声明创建外部绑定声明文件

我使用了在选项1中已经提到的xsd,其中的元素名包含“”(非ASCII)字符:

如果生成类而不指定外部绑定,则得到以下输出:

好了!

现在,如果我稍微更改绑定以生成我选择的类名和变量,我会将binding.xml写成:

代码语言:javascript
复制
<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
    <jxb:globalBindings localScoping="toplevel" />

    <jxb:bindings schemaLocation="some.xsd">
        <jxb:bindings node="//xs:element[@name='Şhİpto']">
            <jxb:class name="ShipTo" />
        </jxb:bindings>
        <jxb:bindings node="//xs:element[@name='Örderperson']">
            <jxb:property name="OrderPerson" />
        </jxb:bindings>
        <jxb:bindings node="//xs:element[@name='Şhİpto']//xs:complexType">
            <jxb:class name="ShipToo" />
        </jxb:bindings>
    </jxb:bindings>

</jxb:bindings>

现在,当我通过指定绑定文件通过eclipse生成类时:

在接下来的步骤中,我选择包和我得到的绑定文件,

注意:如果您没有使用eclipse生成类,您可能需要签出xjc绑定编译器以利用外部绑定文件。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21606248

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档