JAXB - 属性“值”已定义。使用 <jaxb:property> 解决此冲突

Posted

技术标签:

【中文标题】JAXB - 属性“值”已定义。使用 <jaxb:property> 解决此冲突【英文标题】:JAXB - Property "Value" is already defined. Use <jaxb:property> to resolve this conflict 【发布时间】:2011-05-22 14:28:11 【问题描述】:

使用 JAXB 生成 XML 绑定类。

架构基于一组旧的 XML 文件,并包含这个 sn-p:

<xs:complexType name="MetaType">
    <xs:simpleContent>
        <xs:extension base="xs:string">
            <xs:attribute type="xs:string" name="Name" />
            <xs:attribute type="xs:string" name="Scheme" />
            <xs:attribute type="xs:string" name="Value" />
        </xs:extension>
    </xs:simpleContent>
</xs:complexType>

'Value'属性与xs:string的'value'属性冲突,代码生成失败,报错:

com.sun.istack.SAXParseException2: Property "Value" is already defined. Use &lt;jaxb:property> to resolve this conflict. 

【问题讨论】:

【参考方案1】:

答案在于利用 JAXB 绑定 (site-template.xjb):

<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
          xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
          xmlns:xs="http://www.w3.org/2001/XMLSchema"
          version="2.1">
    <bindings schemaLocation="site-template.xsd" version="1.0">
        <!-- Customise the package name -->
        <schemaBindings>
            <package name="com.example.schema"/>
        </schemaBindings>

        <!-- rename the value element -->
        <bindings node="//xs:complexType[@name='MetaType']">
            <bindings node=".//xs:attribute[@name='Value']">
                <property name="ValueAttribute"/>
            </bindings>
        </bindings>
    </bindings>
</bindings>

XPath 表达式定位节点并对其进行重命名,从而避免命名冲突。

使用此绑定 XML 文件,生成的 Java 类最终具有所需的 getValueAttribute()(以及 getValue())。

【讨论】:

我也遇到了这个问题,这个答案解决了,谢谢!想补充一点,如果你使用 Maven jaxb 插件生成 Java 类,你可以把 xjb 文件和实际的 XSD 文件放在同一个资源目录中。 这个解决方案能以某种方式用于远程 XSD 吗?我得到“不是这个汇编的一部分”。错误。谢谢。 我应该把这个site-template.xjb文件放在哪里? @Andremoniy 将文件放在您喜欢的任何位置,然后将其指定为命令行参数。请参阅@rrayasam 答案中的-b 参数 这里有什么帮助,是对 .xjb 文件绑定到 .xsd 的一些解释【参考方案2】:

如果您想避免创建/更改 JAXB 绑定文件,并且不介意对 XSD 进行注释,则可以将 jxb:property 注释添加到属性定义中,例如:

<xs:complexType name="MetaType">
    <xs:simpleContent>
        <xs:extension base="xs:string">
            <xs:attribute type="xs:string" name="Name" />
            <xs:attribute type="xs:string" name="Scheme" />
            <xs:attribute type="xs:string" name="Value">
                <!-- rename property generated by JAXB (avoiding "Value" name conflict) -->
                <xs:annotation>
                    <xs:appinfo>
                        <jxb:property name="valueAttribute"/>
                    </xs:appinfo>
                </xs:annotation>
            </xs:attribute>
        </xs:extension>
    </xs:simpleContent>
</xs:complexType>

适当添加 xs:schema 标记:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
           jxb:version="2.1">

【讨论】:

这对我来说好多了。接受的答案需要我无法管理的设置。我只是想让它工作! 我认为这个答案更适合作为一个正确的问题答案 嗨。我正在尝试使用它来修复我的 .wsdl 文件,但是 wsdl 定义说它们不允许 jxb:version 在 元素中。我怎样才能在那里注入 jxb 命名空间和版本? 更直接的方法。也为我工作! 感谢它的帮助,-p xxx.xjb 更具挑战性。【参考方案3】:

如下所示,为重复属性名称“value”(重复是 JAXB 提供的默认“value”)创建 xxxx.xjb 文件后,运行 XJC 命令创建 JAXB 对象

xjc -p "com.track.doc" -d "C:\JAXBDocuments\prasam\Desktop\JAXB_me\DealerTrace" appSamp.xsd -b xxxx.xjb

appSmp.xsd:-

<xsd:complexType name="range">
    <xsd:simpleContent>
        <xsd:extension base="xsd:string">
             <xsd:attribute name="value" type="xsd:string"/> 
        </xsd:extension>
    </xsd:simpleContent>        
</xsd:complexType>

xxxx.xjb:-

<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
          xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
          xmlns:xs="http://www.w3.org/2001/XMLSchema"
          version="2.1">
    <bindings schemaLocation="appSmp.xsd" version="1.0">

        <schemaBindings>
            <package name="com.track.doc"/>
        </schemaBindings>    
        <bindings node="//xs:complexType[@name='range']">
            <bindings node=".//xs:attribute[@name='value']">
                <property name="valueAttribute"/>
            </bindings>
        </bindings>
    </bindings>
</bindings>

【讨论】:

您好,感谢您的回答。实际上,我遇到了这个问题,所以我找到了这个答案并尝试按照此处提供的步骤操作:我将 appSmp.xsd 和 'xxxx.xjb' 文件与此答案中提供的内容一起放在了一个目录中。更改文件路径并运行以下命令:xjc -p "com.track.doc" -d "path" appSamp.xsd -b xxxx.xjb 仍然出现错误:` [ERROR] schema_reference.4: Failed to read schema document '´path/appSamp.xsd',因为 1) 找不到文档; 2) 文件无法读取; 3) 文档的根元素不是。未知位置`【参考方案4】:

我在使用 Eclipse(尝试了 Helios SR1 和 Juno SR1)和 CXF 2.6.3 的解决方案时遇到了问题。解决方案类似于 Kaitsu 所说的。即 Eclipse 的 New > Web Service 向导将 wsdl 复制到文件夹 WebContent/wsdl 中。我必须自己将 wsdl 和绑定文件放在那里。否则绑定文件给出“不是此编译的一部分”错误。

我无法在 WSDL 中使用内联架构,但它确实可以与答案 #1 中的外部架构一起使用。

我正在使用 CXF Servlet 端点配置选项。在我的 WSDL 中,我有:

<wsdl:port binding="axis2:ConverterSOAP12Binding" name="ConverterSOAP12port_http">
  <soap12:address location="http://localhost/Converter/services/Converter"/>
</wsdl:port>

向导将其生成到我的 web.xml 中,可以正常工作:

<servlet-mapping>
  <servlet-name>cxf</servlet-name>
  <url-pattern>/services/*</url-pattern>
</servlet-mapping>

但它把这个放到 cxf-servlet.xml 中:

<jaxws:endpoint xmlns:tns="http://wtp" id="converterporttype"
implementor="wtp.ConverterPortTypeImpl" wsdlLocation="wsdl/Converter.wsdl"
endpointName="tns:ConverterSOAP12port_http" serviceName="tns:Converter"
address="/ConverterSOAP12port_http">
  <jaxws:features>
    <bean class="org.apache.cxf.feature.LoggingFeature" />
  </jaxws:features>
</jaxws:endpoint>

我不得不将地址更改为完整的 URL,如下所示:

address="http://localhost:8080/Converter/services/Converter">

【讨论】:

【参考方案5】:

这些绑定都不适合我,我收到了这个错误:

[ERROR] La evaluación de XPath de ".//xs:attribute[@name='Value']" produce un nodo de destino vacío

它产生了一个空的目标节点...然后我意识到(经过 30 分钟的绝望)我的绑定针对的是 complexType 而不是元素。答案在我的 xsd 文件中。

谢谢

【讨论】:

【参考方案6】:

另一个答案中提到的这个绑定文件不适用于 CXF 3.0.0。 请注意,jaxb 命名空间有一个元素“绑定”,命名空间 jaxws 也是如此,所以我们需要声明它们:

<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
          xmlns="http://java.sun.com/xml/ns/jaxws"
          xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
          xmlns:xs="http://www.w3.org/2001/XMLSchema"
          wsdlLocation="mesh.wsdl" >
    <bindings node="wsdl:definitions/wsdl:types/xs:schema[...">
        <jaxb:bindings node="./xs:element[@name='Profiles']">
            <jaxb:property name="ProfilesElement"/>
        </jaxb:bindings>
    </bindings>
</bindings>

在我的例子中,架构已经在 WSDL 中,所以我不必指定 schemaLocation 属性。

【讨论】:

这是包含jaxb:property 的唯一答案,但我不明白这里的答案与文件的其余部分有何关系。一方面,我在尝试修复的 WSDL 文件中看不到 bindings 标记。 此 XML 位于 .xjb 文件中。这个其他问题有一个例子:***.com/questions/23961421【参考方案7】:

您也可以在命令行和插件中使用参数 -XautoNameResolution 让 jxc 解析名称,如果您不关心类上的名称。

【讨论】:

以上是关于JAXB - 属性“值”已定义。使用 <jaxb:property> 解决此冲突的主要内容,如果未能解决你的问题,请参考以下文章

使用 JAXB 的具有属性和内容的 XML 元素

Java/JAXB:根据属性将 Xml 解组为特定子类

在Jaxb转换的Enum类中检索@XmlEnumValue注释属性值

自定义 jaxb 编组输出

当节点包含值时,使用 JAXB 将 XML 转换为对象

Xml Jaxb 命名空间和属性顺序