我有3个相互依赖的xsd文件来构建我的元素定义。每个xsd文件都有其自己的名称空间。当我使用JAXB
xjc生成类时,得到3个相应的包。到目前为止,一切都很好。
当我想使用解组器进行架构验证时,就会出现我的问题。为了避免不得不读取xsd文件,我从被解组的相关类中动态生成了模式。但是,由于该类依赖于其他2个包中的对象,因此除非我指定所有3个包,否则它无法生成架构。这已经不是一个非常实用的解决方案,因为它要求我提前知道对象层次结构/依赖关系树,并相应地指定包列表。
当我尝试使用SchemaFactory(SchemaFactory.newSchema(Source
[]))从3个生成的架构中创建新架构时,我遇到了更大的问题。显然,将架构提供给架构工厂的顺序对于解析依赖关系至关重要。如果数组中的第一个架构依赖于数组中最后一个元素的类型定义,则会收到解决错误:
org.xml.sax.SAXParseException: src-resolve: Cannot resolve the name 'ns1:InCalculationDataType' to a(n) 'type definition' component.
如果我修改顺序,然后将第三个架构放在第一位,那么它将成功执行而不会出现错误。
这使得几乎不可能编写一种相当通用的方法,而不得不为每种XSD情况单独编写代码。
我有什么办法可以减轻这个问题?有什么方法可以迫使SchemaFactory首先读取所有内容,然后在发现任何错误时才生成错误?我知道您可以创建一个ErrorHandler,但是JavaDocs指出,如果抛出致命错误,则任何进一步的处理都是不可靠的。
编辑
只是为了让我省心,我试图创建一个错误处理程序,该程序忽略了非致命错误(只是记录了它们),但是生成的模式不可靠,无法正确验证xml错误。因此,它对我没有任何价值。
结束编辑
任何建议或想法将不胜感激。
谢谢!
埃里克
经过大量搜索,我终于找到了答案。希望这会帮助其他人。已经存在与此问题相关的其他线程,但是在不知道正确的关键字的情况下,我找不到响应。
解决方案是对架构工厂使用LSResourceResolver。即:
schemaFactory.setResourceResolver(new LSResourceResolver(){})
LSResourceResolver()负责返回XSD所需的包含/导入资源。
搜索LSResourceResolver的SO中发现一些有用的主题:http://codingdict.com/questions/155814
我将在以后有更多时间的时候尝试发布自己的解决方案,但它会紧跟上述两个链接中已经提出的建议(通过使用Strings而不是stream简化了我的工作…)。
编辑
如所承诺的,这是我最后得到的代码片段:
// get the schemas used by this class
final Map<String, String> schemas = new HashMap<String,String>();
schemas.putAll(generateSchemas(jc));
List<StreamSource> sources = new ArrayList<StreamSource>();
for( String schema : schemas.values() )
sources.add( new StreamSource( new ByteArrayInputStream(schema.getBytes())));
SchemaFactory sf = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI );
sf.setResourceResolver(new LSResourceResolver() {
@Override
public LSInput resolveResource(String type, final String namespaceURI, String publicId, String systemId, String baseURI){
logger.debug( "Need to resolve Resource: " + namespaceURI );
return new LSInput(){
@Override
public String getStringData() {
// return the schema if found
if( schemas.containsKey(namespaceURI)){
if( logger.isTraceEnabled())
logger.trace("resourceResolver: Resolving schema for namespace: " + namespaceURI + schemas.get(namespaceURI) );
return schemas.get(namespaceURI);
}
else
return null;
}
@Override
public Reader getCharacterStream() {
return null;
}
@Override
public void setCharacterStream(Reader paramReader) {
}
@Override
public InputStream getByteStream() {
return null;
}
@Override
public void setByteStream(InputStream paramInputStream) {
}
@Override
public void setStringData(String paramString) {
}
@Override
public String getSystemId() {
return null;
}
@Override
public void setSystemId(String paramString) {
}
@Override
public String getPublicId() {
return null;
}
@Override
public void setPublicId(String paramString) {
}
@Override
public String getBaseURI() {
return null;
}
@Override
public void setBaseURI(String paramString) {
}
@Override
public String getEncoding() {
return null;
}
@Override
public void setEncoding(String paramString) {
}
@Override
public boolean getCertifiedText() {
return false;
}
@Override
public void setCertifiedText(boolean paramBoolean) {
}
};
}
});
// validate the schema
u.setSchema(sf.newSchema(sources.toArray(new StreamSource[]{})));
和方法generateSchemas(jc):
private Map<String, String> generateSchemas (JAXBContext jaxbContext) throws JAXBException{
// generate the schemas
final Map<String, ByteArrayOutputStream> schemaStreams = new LinkedHashMap<String,ByteArrayOutputStream>();
try {
jaxbContext.generateSchema(new SchemaOutputResolver(){
@Override
public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
logger.debug( "GenerateSchemas: adding namespace: " + namespaceUri);
schemaStreams.put(namespaceUri, out);
StreamResult streamResult = new StreamResult(out);
streamResult.setSystemId("");
return streamResult;
}});
} catch (IOException e) {
// no IO being performed. Can safely ignore any IO exception.
}
// convert to a list of string
Map<String,String> schemas = new LinkedHashMap<String,String>();
for( Map.Entry<String, ByteArrayOutputStream> entry : schemaStreams.entrySet() ){
String schema = entry.getValue().toString();
String namespace = entry.getKey();
schemas.put(namespace, schema);
}
// done
return schemas;
}
结束编辑
我希望这可以在将来对其他人有所帮助。
谢谢,
3.1 顺序控制结构 程序是一个语句序列,执行程序就是按特定的次序执行程序中的语句。程序中执行点的 变迁称为控制流程,当执行到程序中的某一条语句时,也说控制转到了该语句。由于复杂问 题的解法可能涉及复杂的执行次序,因此编程语言必须提供表达复杂控制流程的手段,称为 编程语言的控制结构。 程序的控制流程可以用流程图(flowchart)来形象地表示。流程图采用标准化的图形符 号来描述程序的执行步骤,是
主要内容:顺序表的初始化顺序表,全名 顺序存储结构,是 线性表的一种。通过《 什么是线性表》一节的学习我们知道,线性表用于存储逻辑关系为“一对一”的数据,顺序表自然也不例外。 不仅如此,顺序表对数据的物理存储结构也有要求。 顺序表存储数据时,会提前申请一整块足够大小的物理空间,然后将数据依次存储起来,存储时做到数据元素之间不留一丝缝隙。 例如,使用顺序表存储集合 ,数据最终的存储状态如图 1 所示: 图 1 顺序存储结
主要内容:图的顺序存储结构C语言实现使用图结构表示的数据元素之间虽然具有“多对多”的关系,但是同样可以采用顺序存储,也就是使用数组有效地存储图。 使用数组存储图时,需要使用两个数组,一个数组存放图中顶点本身的数据(一维数组),另外一个数组用于存储各顶点之间的关系(二维数组)。 存储图中各顶点本身数据,使用一维数组就足够了;存储顶点之间的关系时,要记录每个顶点和其它所有顶点之间的关系,所以需要使用二维数组。 不同类型的图,存储的方式略
问题内容: 当前,我的项目使用,因此当我按此列排序时,它是根据中的顺序进行排序的,效果很好。但是我需要在中添加一些附加值,这些附加值需要插入到枚举值列表中的不同位置,并且不能仅仅添加到底部以保持正确的排序顺序。 如果这样做,我的数据库将会混乱。我将不得不编写一些脚本来将所有这些序数值转换为正确的新序数。有可能以后必须添加更多状态。由于必须修复数据库中的所有数据,因此只需要执行一次,因为这将是一项艰
顺序结构 #include <stdio.h> #include <stdlib.h> int main01(void) { printf("%d \n", 1);//顺序结构,从上往下执行,从main函数开始 printf("%d \n", 11); printf("%d \n", 111); printf("%d \n", 1111); sys
我在项目中使用JMH基准测试。我用@Benchmark注释了方法1和方法2。我希望顺序是:method1、method2、method 1、methad2……等等……这意味着:我希望方法2紧跟在方法1之后。有办法做到这一点吗? 谢谢大家!