我有两套XSD,一套用于生成基于RPC的调用,另一套用于定义特定于产品的方法。 RpcType对象(由JAXB2生成)具有由以下定义的'setRpcOperation'方法:
RpcType.setRpcOperation(JAXBElement<? extends RpcOperationType>)
'RpcOperation'对象应该是上面描述的'特定产品方法'。一个例子是(也由JAXB2生成):
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "get-user-stats", propOrder = {
"reset"
})
public class GetUserStats {
protected Boolean reset;
/**
* Gets the value of the reset property.
*
* @return
* possible object is
* {@link Boolean }
*
*/
public Boolean isReset() {
return reset;
}
/**
* Sets the value of the reset property.
*
* @param value
* allowed object is
* {@link Boolean }
*
*/
public void setReset(Boolean value) {
this.reset = value;
}
}
现在,是否可以创建一个'GetUserStatus'实例并通过setRpcOperation将其添加到RpcType对象中?
答案 0 :(得分:3)
这种情况很常见:
以下是可以这样做的一种方式:
邮件架构 - message.xsd
有一个XML架构来表示您的邮件信封。引入一种类型来表示消息的正文。此类型将由不同的有效负载扩展。
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/message"
xmlns="http://www.example.org/message"
elementFormDefault="qualified">
<xsd:element name="message">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="body" type="body"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="body">
</xsd:complexType>
</xsd:schema>
有效负载架构 - customer.xsd
此架构对应于特定类型的消息有效内容。请注意客户类型如何从消息架构中扩展正文类型。
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
targetNamespace="http://www.example.org/customer"
xmlns="http://www.example.org/customer"
xmlns:m="http://www.example.org/message"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xsd:import schemaLocation="message.xsd" namespace="http://www.example.org/message"/>
<xsd:complexType name="customer">
<xsd:complexContent>
<xsd:extension base="m:body">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
<强> org.example.message.package-信息强>
此类是从message.xsd生成的。
@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.example.org/message", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.example.message;
<强> org.example.message.Message 强>
此类是从message.xsd生成的。
package org.example.message;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"body"
})
@XmlRootElement(name = "message")
public class Message {
@XmlElement(required = true)
protected Body body;
public Body getBody() {
return body;
}
public void setBody(Body value) {
this.body = value;
}
}
<强> org.example.message.Body 强>
此类是从message.xsd生成的。
package org.example.message;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "body")
public class Body {
}
<强> org.example.customer.package-信息强>
此类是从customer.xsd生成的。
@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.example.org/customer", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.example.customer;
<强> org.example.customer.Customer 强>
此类是从customer.xsd生成的。
package org.example.customer;
import javax.xml.bind.annotation.*;
import org.example.message.Body;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "customer", propOrder = {
"name"
})
public class Customer extends Body {
@XmlElement(required = true)
protected String name;
public String getName() {
return name;
}
public void setName(String value) {
this.name = value;
}
}
演示班
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import org.example.customer.*;
import org.example.message.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Message.class, Customer.class);
Message message = new Message();
Customer customer = new Customer();
customer.setName("Jane Doe");
message.setBody(customer);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(message, System.out);
}
}
<强>输出强>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<message xmlns="http://www.example.org/message" xmlns:ns2="http://www.example.org/customer">
<body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:customer">
<ns2:name>Jane Doe</ns2:name>
</body>
</message>
编辑#1
回答您的第二个问题(Cast JAXB2 generated object to JAXBElement?)
我没有看到JAXBElement在这个例子中发挥作用。我能够运行以下代码:
import generated.GetFailedLoginCount;
import ietf.params.xml.ns.netconf.base._1.RpcType;
public class Demo {
public static void main(String[] args) {
RpcType rpc = new RpcType();
rpc.setMessageId("123");
GetFailedLoginCount rpcOperation = new GetFailedLoginCount();
rpc.setRpcOperation(rpcOperation);
}
}
编辑#2
将导入更改为导入http://www.iana.org/assignments/xml-registry/schema/netconf.xsd后,我看到的行为与您相同。
要正确设置属性,您需要执行以下操作:
RpcType rpc = new RpcType();
GetFailedLoginCount rpcOperation = new GetFailedLoginCount();
rpcOperation.setReset(true);
JAXBElement<GetFailedLoginCount> rpcOperationJE = new JAXBElement(new QName("foo"), GetFailedLoginCount.class, rpcOperation);
rpc.setRpcOperation(rpcOperationJE);
JAXBElement提供GetFailedLoginCount值的元素名称。这是必需的,因为与rpcOperation属性对应的元素是可替换的:
<xs:element name="get-config" type="getConfigType" substitutionGroup="rpcOperation" />
在导入netconf.xsd的模式中,您应该有一个类型为“get-failed-login-count”的元素,可以替换为“rpcOperation”。这将作为QName提供给JAXBElement。由于我们使用了元素名称“foo”,因此架构更新将如下所示:
<xs:element name="foo" type="get-failed-login-count" substitutionGroup="rpcOperation" />
答案 1 :(得分:0)
好的,所以这里是我想要做的一部分。上面的例子非常有用,但我仍然无法创建JAXBElement:
可以找到基本信封:http://www.iana.org/assignments/xml-registry/schema/netconf.xsd
rpcOperationType的有效负载(我添加了**行):
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:dmi="http://xml.juniper.net/dmi"
** xmlns:netconf="urn:ietf:params:xml:ns:netconf:base:1.0"
>
**<xs:import schemaLocation="netconf.xsd" namespace="urn:ietf:params:xml:ns:netconf:base:1.0"/>
<!-- get-failed-login-count -->
<xs:complexType name="get-failed-login-count">
**<xs:complexContent>
** <xs:extension base="netconf:rpcOperationType">
<xs:annotation>
<xs:appinfo>
<dmi:rpc-info>
<name>Get failed login count for Authentication failure and Exceeded user</name>
<description>
This command returns the Number of Logins refused due to exceeding allowed limits and Auth failure (24 hour moving window)
</description>
<rpc-reply-tag>failed-login-count</rpc-reply-tag>
</dmi:rpc-info>
</xs:appinfo>
</xs:annotation>
<xs:sequence>
<xs:element name="reset" type="xs:boolean" minOccurs="0">
<xs:annotation>
<xs:appinfo>
<dmi:param-info>
<name>Reset Stats</name>
<description>
This will govern the reseting of this statistics data. By default, the data is not reset.
</description>
</dmi:param-info>
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:sequence>
** </xs:extension>
**</xs:complexContent>
</xs:complexType>
现在,生成的GetFailedLogin类扩展了RpcOperationType,但我不确定如何在RpcType对象中设置它:
RpcType rpc = new RpcType();
rpc.setMessageId("123");
GetFailedLoginCount rpcOperation = new GetFailedLoginCount();
rpc.setRpcOperation(); // Expects JAXBElement<? Extends RpcOperationType>