是否有任何JAXB绑定可以告诉JAXB代码生成器将Java类生成为abstract
,而不必在XSD中将相应的XML类型标记为abstract
?
情况如下:
>
myschema.xsd
我使用内联JAXB绑定(“inline”==“直接在模式中”)来指示应该生成JAXB类的包(my.package.JAXB
):
<xs:annotation>
<xs:appinfo>
<jxb:schemaBindings>
<jxb:package name="my.package.jaxb"/>
</jxb:schemaBindings>
</xs:appinfo>
</xs:annotation>
我使用内联JAXB绑定为我的每个复杂类型(在本例中my.package.impl.MyAbstractClass
、my.package.impl.MyAclass
和my.package.impl.MybClass
)指示实现类的名称:
<xs:complexType name="myAbstractType" abstract="true">
<xs:annotation>
<xs:appinfo>
<jxb:class implClass="my.package.impl.MyAbstractClass"/>
</xs:appinfo>
</xs:annotation>
...
</xs:complexType>
<xs:complexType name="myAType">
<xs:annotation>
<xs:appinfo>
<jxb:class implClass="my.package.impl.MyAClass"/>
</xs:appinfo>
</xs:annotation>
<xs:complexContent>
<xs:extension base="myAbstractType">
...
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="myBType">
<xs:annotation>
<xs:appinfo>
<jxb:class implClass="my.package.impl.MyBClass"/>
</xs:appinfo>
</xs:annotation>
<xs:complexContent>
<xs:extension base="myAbstractType">
...
</xs:extension>
</xs:complexContent>
</xs:complexType>
我从模式生成JAXB类。这导致:
my.package.jaxb
|- MyAbstractType
|- MyAType (extends MyAbstractClass)
|- MyBType (extends MyAbstractClass)
我自己编写类:
my.package.impl
|- MyAbstractClass (extends MyAbstractType)
|- MyAClass (extends MyAType)
|- MyBClass (extends MyBType)
使用这两个类层次结构这样做的原因是,我可以将生成的代码(my.package.jaxb.*
)与手动代码(my.package.impl.*
)分开。这样,当XSD中发生更改时,我可以重新生成my.package.jaxb.*
类,并在我的手动my.package.impl.*
类中进行一些更改,以合并新的行为。
到目前为止还好。问题是在MyAbstractClass
中,我想定义一个html" target="_blank">抽象方法······
protected abstract void doSomething();
...然后由myaclass
和mybclass
以不同的方式实现。但是,生成的MyAtype
和MyBType
类现在有编译错误,因为它们没有声明为抽象,而是继承了一个抽象方法(注意它们都扩展了MyAbstractClass
)。
我不能在XSD中将它们声明为抽象(abstract=“true”
),因为每当我在XML中声明Myatype
或Mybtype
类型的元素时,这样做将导致以下错误:
cvc-type.2: The type definition cannot be abstract for element someElementName.
我希望使用一些JAXB绑定来告诉JAXB代码生成器将类Myatype
和Mybtype
生成为Abstract
,而不必将XML类型标记为Abstract
。有这样的绑定吗?到目前为止我还没能找到它。
很抱歉解释得太长,并提前表示感谢。
我最终创建了一个XJC插件。代码如下:
import java.lang.reflect.Method;
import javax.xml.namespace.QName;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import com.sun.codemodel.JMod;
import com.sun.codemodel.JMods;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.outline.ClassOutline;
import com.sun.tools.xjc.outline.Outline;
import com.sun.tools.xjc.reader.xmlschema.bindinfo.BIDeclaration;
import com.sun.tools.xjc.reader.xmlschema.bindinfo.BindInfo;
import com.sun.xml.xsom.XSAnnotation;
public class AbstractModifierPlugin extends com.sun.tools.xjc.Plugin {
private static final QName ABSTRACT_QNAME = new QName("http://www.example.com/jaxb/abstract-modifier/1-0", "abstract");
private static final String SET_FLAG_METHOD_NAME = "setFlag";
private static final String OPTION_NAME = "Xabstract-modifier";
@Override
public String getOptionName() {
return OPTION_NAME;
}
@Override
public String getUsage() {
return " -" + OPTION_NAME + " : marks as abstract the generated classes corresponding to XML types marked with "
+ "<xs:annotation><xs:appinfo><" + ABSTRACT_QNAME + "/></xs:appinfo></xs:annotation>";
}
@Override
public boolean run(Outline outline, Options options, ErrorHandler errorHandler) throws SAXException {
Method setFlagMethod = null;
try {
// There is no method to make a class abstract; we can only use setFlag, which is private, so
// we must get it via reflection and make it accessible.
setFlagMethod = JMods.class.getDeclaredMethod(SET_FLAG_METHOD_NAME, int.class, boolean.class);
setFlagMethod.setAccessible(true);
} catch (Throwable e) {
System.err.println("There was an error retrieving the " + JMods.class.getName() + "." + SET_FLAG_METHOD_NAME
+ " method (see below) => it will not be possible to set any class' abstract flag => this plugin will abort");
e.printStackTrace();
return false;
}
for (ClassOutline classOutline : outline.getClasses()) {
if (hasAbstractAnnotation(classOutline)) {
try {
setFlagMethod.invoke(classOutline.implClass.mods(), JMod.ABSTRACT, true);
} catch (Throwable e) {
System.err.println("It was not possible to make " + classOutline.implClass.fullName()
+ " abstract (see below)");
e.printStackTrace();
}
}
}
return true;
}
protected boolean hasAbstractAnnotation(ClassOutline classOutline) {
XSAnnotation annotation = classOutline.target.getSchemaComponent().getAnnotation();
if (annotation != null) {
Object innerAnnotation = annotation.getAnnotation();
if (innerAnnotation instanceof BindInfo) {
for (BIDeclaration bindInfoDeclaration : (BindInfo) innerAnnotation) {
if (ABSTRACT_QNAME.equals(bindInfoDeclaration.getName())) {
return true;
}
}
}
}
return false;
}
}
下面是abstract.xsd
,它定义了
元素,您需要使用该元素来指示生成的类应该是抽象的:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.com/jaxb/abstract-modifier/1-0"
xmlns:tns="http://www.example.com/jaxb/abstract-modifier/1-0"
elementFormDefault="qualified">
<element name="abstract"/>
</schema>
用法(按照我最初问题中的示例):
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
...
xmlns:abstract="http://www.example.com/jaxb/abstract-modifier/1-0"
...>
<xs:complexType name="myAbstractType" abstract="true">
<xs:annotation>
<xs:appinfo>
<jxb:class implClass="my.package.impl.MyAbstractClass"/>
</xs:appinfo>
</xs:annotation>
...
</xs:complexType>
<xs:complexType name="myAType">
<xs:annotation>
<xs:appinfo>
<jxb:class implClass="my.package.impl.MyAClass"/>
<!-- This tells the AbstractModifierPlugin to make the
generated class abstract -->
<abstract:abstract/>
</xs:appinfo>
</xs:annotation>
<xs:complexContent>
<xs:extension base="myAbstractType">
...
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="myBType">
<xs:annotation>
<xs:appinfo>
<jxb:class implClass="my.package.impl.MyBClass"/>
<!-- This tells the AbstractModifierPlugin to make the
generated class abstract -->
<abstract:abstract/>
</xs:appinfo>
</xs:annotation>
<xs:complexContent>
<xs:extension base="myAbstractType">
...
</xs:extension>
</xs:complexContent>
</xs:complexType>
我不得不说,我发现很难找到所有必要的文档来找出如何做到这一点。如果我找到时间,我会在这里发布一个更长的解释;就目前而言,我希望至少代码会有所帮助。免责声明:我不知道这是否是最好的方法,但我必须依赖的类文档非常松散(而且设计得不是很好),这是我能想到的最好的方法。
我希望这能有所帮助。如果有人想使用这个代码,请便。
错误CS0234:类型或命名空间名称com.sushi.hangover”中不存在。是否缺少程序集引用? 我有一个Android绑定项目,它有从多个接口继承的类,但这些接口没有生成,因此依赖于它们的所有公共类都无法绑定。 如您所见,该接口的没有设置为,因此不会生成C#代码,但是begin生成了依赖于该接口的公共类: 绑定在将接口名称从转换为时,可以识别接口。 是否有任何方法可以强制创建这些接口,而
问题是: 我有一个叫做Schema的基类,它是抽象的,它是一个未生成的类。我有两个从Schema继承生成的JAXB类:FixedWidthSchema和DelimitedSchema。 我使用外部绑定(xjb)文件来指定XSD和Java类之间的映射。 在基类模式中,我定义了几个方法: 公共架构静态创建(Model m),它从提供的模型创建架构。 公共抽象Writer marshal(),它将当前架
我目前正在尝试使用JaxB,但对于一个相对简单的示例,我并不是很成功。我的示例如下: 我所有的尝试(甚至编组)都失败了。我浏览了BlaiseDoughan的博客,包括http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-xsitype.html但他们似乎对我的例子都没有帮助。我很可能误用了他的例子。在我看来,我的示例应该是JaxB中
问题内容: 我正在尝试使用JAXB解组一些XML,但出现“无法创建…的实例”异常。我知道为什么- 它试图建立一个抽象类的实例。我想要的是让它成为特定实现类的实例。我的目标是对setter方法进行特定于类的检查。对于BarImpl,也许“ qux”是有效的baz值,但BarImpl2想要做其他事情。 我没有通过注释Foo来实现这一目标,但是如果我不注释bar,事情就会变得很丑。 问题答案: 您可以执
我有一个子类,它声明了我的抽象超类中的所有方法,但它仍然给我一个错误,说明我的类不是抽象的。我不知道为什么会抛出这个错误。 我得到的具体错误是 PhoneBookEntry.java: 1:错误:PhoneBookEntry不是抽象的,并且不会覆盖可比中的抽象方法compareTo(Object) 我的问题代码: 还有我的子类:
问题内容: 我有一个包含带有抽象超类的JAXB注释类的程序包。我想在Web服务接口中使用此超类,因此可以将任何子类作为参数传递。当我这样做时,会引发异常: 可以手动将marshall / unmarshall&参数作为字符串传递,但我想避免这种情况。有什么想法怎么做? 问题答案: 您是否在Web服务请求中指定了具体的实现?这对我来说很好: 抽象基类: 实现类: Web服务方法: 请求: