java 使用命名空间扩展的 jaxb 致命验证错误
java jaxb fatal validation error using namespace extensions
我有一个基础 XML 架构,我必须使用 xs:redefine 对其进行扩展,然后从第二个架构中添加一些扩展。解组时出现致命错误:
cvc-complex-type.2.4.d: 发现以元素 'base:TypeTwo' 开头的无效内容。此时不应有子元素。
即使其他解析器说 XML 完全有效。
- 所以我在命名空间下的 base.xsd 中有我的基本标签
“http://www.example.com/base”
- 我的扩展标签在 extension.xsd
在命名空间“http://www.example.com/extension”下
- 还有我的
redefine.xsd 中的重新定义,它导入 extension.xsd
所以我的基本标签是
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element ref="TypeThree" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="TypeTwo">
</xs:complexType>
<xs:element name="TypeTwo" type="TypeTwo" />
<xs:group name="TypeThreeExtension">
<xs:sequence />
</xs:group>
<xs:complexType name="TypeThree">
<xs:sequence>
<xs:group maxOccurs="unbounded" minOccurs="0" ref="TypeThreeExtension" />
</xs:sequence>
</xs:complexType>
<xs:element name="TypeThree" type="TypeThree" />
只有一个根和两个元素,一个带有一组用于扩展。
我的扩展标签是:
<xs:schema targetNamespace="http://www.example.com/extension"
elementFormDefault="qualified"
xmlns="http://www.example.com/extension"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:base="http://www.example.com/base"
xmlns:ext="http://www.example.com/extension"
>
<xs:import schemaLocation="base.xsd" namespace="http://www.example.com/base"/>
<xs:complexType name="ExtTypeOne">
<xs:sequence>
<xs:element ref="base:TypeTwo" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:element name="ExtTypeOne" type="ExtTypeOne" />
所以只有一种额外的类型,它包含一种 base 类型(这似乎是重要因素)。
redefine.xsd是
<xs:schema targetNamespace="http://www.example.com/base"
elementFormDefault="qualified" xmlns="http://www.example.com/base"
xmlns:ext="http://www.example.com/extension" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="extension.xsd" namespace="http://www.example.com/extension" />
<xs:redefine schemaLocation="base.xsd">
<xs:group name="TypeThreeExtension">
<xs:sequence>
<xs:element ref="ext:ExtTypeOne" maxOccurs="unbounded" />
</xs:sequence>
</xs:group>
</xs:redefine>
所以我在这里只是扩展了基础 TypeThreeExtension 组,这样我现在可以在下面添加 ExtTypeOne 标签。这基本上允许标签的结构是:
- 基地
- 分机
- 基地
当我加载以下 XML 进行解组时...
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root
xmlns="http://www.example.com/base"
xmlns:base="http://www.example.com/base"
xmlns:ext="http://www.example.com/extension">
<TypeThree>
<ext:ExtTypeOne>
<base:TypeTwo/>
</ext:ExtTypeOne>
</TypeThree>
</Root>
我收到以下错误:
ValidationEvent 1 - 行:8,严重性:2,cvc-complex-type.2。4.d:发现以元素 'base:TypeTwo' 开头的无效内容。此时不需要子元素。
无论我做什么我都无法摆脱这个错误。事实上 - 即使当我 将对象编组 到 XML 时,JAXB 实际上创建了 XML 然后它(在解组时)报告是无效的。这是 JAXB 错误吗?
FWIW - 我可以说这是导致它的 base-ext-base 嵌套。将重新定义的模式中的类型嵌套在第二个模式的标记下是否无效?我需要创建不同的目标名称空间还是什么?
我快要死了...
我最近弄清楚这里发生了什么。我在解组器中使用的 Schema 对象是从 JaxbContext 对象动态生成的。代码看起来像这样...
CONTEXT = JAXBContext.newInstance(Root.class);
final Collection<StreamResult> results = new ArrayList<StreamResult>();
CONTEXT.generateSchema(new SchemaOutputResolver() {
@Override
public Result createOutput(String arg0, String suggestedFileName) throws IOException {
System.out.println("create output: "+arg0+" "+suggestedFileName);
StreamResult result = new StreamResult();
result.setSystemId(suggestedFileName);
results.add(result);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
result.setOutputStream(baos);
return result;
}
});
Collection<StreamSource> sss = new ArrayList<StreamSource>();
for(StreamResult r : results){
ByteArrayOutputStream baos = ((ByteArrayOutputStream)( r.getOutputStream()));
StreamSource ss = new StreamSource(new ByteArrayInputStream(baos.toByteArray()),r.getSystemId());
sss.add(ss);
}
Schema sm = schemaFactory.newSchema(sss.toArray(new StreamSource[]{}));
但是,动态生成的架构似乎没有包含足够的详细信息来对此类架构扩展执行正确的验证。所以我不得不用一种更直接的技术来替换这种技术,这种技术直接在类路径上引用 XSD 。此方法的代码如下所示:
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(new Source[]{
new StreamSource(new File("./src/main/resources/redefine.xsd"))
});
这个新的 Schema 对象验证了 XML,没有任何验证错误。
我有一个基础 XML 架构,我必须使用 xs:redefine 对其进行扩展,然后从第二个架构中添加一些扩展。解组时出现致命错误: cvc-complex-type.2.4.d: 发现以元素 'base:TypeTwo' 开头的无效内容。此时不应有子元素。 即使其他解析器说 XML 完全有效。
- 所以我在命名空间下的 base.xsd 中有我的基本标签 “http://www.example.com/base”
- 我的扩展标签在 extension.xsd 在命名空间“http://www.example.com/extension”下
- 还有我的 redefine.xsd 中的重新定义,它导入 extension.xsd
所以我的基本标签是
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element ref="TypeThree" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="TypeTwo">
</xs:complexType>
<xs:element name="TypeTwo" type="TypeTwo" />
<xs:group name="TypeThreeExtension">
<xs:sequence />
</xs:group>
<xs:complexType name="TypeThree">
<xs:sequence>
<xs:group maxOccurs="unbounded" minOccurs="0" ref="TypeThreeExtension" />
</xs:sequence>
</xs:complexType>
<xs:element name="TypeThree" type="TypeThree" />
只有一个根和两个元素,一个带有一组用于扩展。
我的扩展标签是:
<xs:schema targetNamespace="http://www.example.com/extension"
elementFormDefault="qualified"
xmlns="http://www.example.com/extension"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:base="http://www.example.com/base"
xmlns:ext="http://www.example.com/extension"
>
<xs:import schemaLocation="base.xsd" namespace="http://www.example.com/base"/>
<xs:complexType name="ExtTypeOne">
<xs:sequence>
<xs:element ref="base:TypeTwo" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:element name="ExtTypeOne" type="ExtTypeOne" />
所以只有一种额外的类型,它包含一种 base 类型(这似乎是重要因素)。
redefine.xsd是
<xs:schema targetNamespace="http://www.example.com/base"
elementFormDefault="qualified" xmlns="http://www.example.com/base"
xmlns:ext="http://www.example.com/extension" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="extension.xsd" namespace="http://www.example.com/extension" />
<xs:redefine schemaLocation="base.xsd">
<xs:group name="TypeThreeExtension">
<xs:sequence>
<xs:element ref="ext:ExtTypeOne" maxOccurs="unbounded" />
</xs:sequence>
</xs:group>
</xs:redefine>
所以我在这里只是扩展了基础 TypeThreeExtension 组,这样我现在可以在下面添加 ExtTypeOne 标签。这基本上允许标签的结构是:
- 基地
- 分机
- 基地
- 分机
当我加载以下 XML 进行解组时...
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root
xmlns="http://www.example.com/base"
xmlns:base="http://www.example.com/base"
xmlns:ext="http://www.example.com/extension">
<TypeThree>
<ext:ExtTypeOne>
<base:TypeTwo/>
</ext:ExtTypeOne>
</TypeThree>
</Root>
我收到以下错误:
ValidationEvent 1 - 行:8,严重性:2,cvc-complex-type.2。4.d:发现以元素 'base:TypeTwo' 开头的无效内容。此时不需要子元素。
无论我做什么我都无法摆脱这个错误。事实上 - 即使当我 将对象编组 到 XML 时,JAXB 实际上创建了 XML 然后它(在解组时)报告是无效的。这是 JAXB 错误吗?
FWIW - 我可以说这是导致它的 base-ext-base 嵌套。将重新定义的模式中的类型嵌套在第二个模式的标记下是否无效?我需要创建不同的目标名称空间还是什么?
我快要死了...
我最近弄清楚这里发生了什么。我在解组器中使用的 Schema 对象是从 JaxbContext 对象动态生成的。代码看起来像这样...
CONTEXT = JAXBContext.newInstance(Root.class);
final Collection<StreamResult> results = new ArrayList<StreamResult>();
CONTEXT.generateSchema(new SchemaOutputResolver() {
@Override
public Result createOutput(String arg0, String suggestedFileName) throws IOException {
System.out.println("create output: "+arg0+" "+suggestedFileName);
StreamResult result = new StreamResult();
result.setSystemId(suggestedFileName);
results.add(result);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
result.setOutputStream(baos);
return result;
}
});
Collection<StreamSource> sss = new ArrayList<StreamSource>();
for(StreamResult r : results){
ByteArrayOutputStream baos = ((ByteArrayOutputStream)( r.getOutputStream()));
StreamSource ss = new StreamSource(new ByteArrayInputStream(baos.toByteArray()),r.getSystemId());
sss.add(ss);
}
Schema sm = schemaFactory.newSchema(sss.toArray(new StreamSource[]{}));
但是,动态生成的架构似乎没有包含足够的详细信息来对此类架构扩展执行正确的验证。所以我不得不用一种更直接的技术来替换这种技术,这种技术直接在类路径上引用 XSD 。此方法的代码如下所示:
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(new Source[]{
new StreamSource(new File("./src/main/resources/redefine.xsd"))
});
这个新的 Schema 对象验证了 XML,没有任何验证错误。