假设我有一个 XML 文档(表示为文本、W3C DOM 等),还有一个 XML 模式。 XML 文档具有架构定义的所有正确元素,但顺序错误。
如何使用模式对文档中的元素进行“重新排序”以符合模式定义的顺序?
我知道这应该是可能的,可能使用 XSOM ,因为 JAXB XJC 代码生成器使用元素的正确序列化顺序注释其生成的类。
但是,我对 XSOM API 并不熟悉,而且它非常密集,所以我希望你们中的一些人对此有一些经验,并能为我指明正确的方向。类似于“此父元素内允许使用哪些子元素,以什么顺序排列?”
我举个例子。
我有一个这样的 XML 文档:
<A>
<Y/>
<X/>
</A>
我有一个 XML 模式,它表示 <A>
的内容必须是 <X>
其次是 <Y>
.现在很明显,如果我尝试根据模式验证文档,它会失败,因为 <X>
和 <Y>
顺序错误。但是我事先知道我的文档是“错误的”,所以我还没有使用模式来验证。但是,我确实知道我的文档包含架构定义的所有正确元素,只是顺序错误。
我想做的是以编程方式检查架构(可能使用 XSOM - 它是 XML 架构的对象模型),并询问 <A>
的内容是什么应该。 API 将公开“您需要一个 <X>
后跟一个 <Y>
”的信息。
所以我使用我的 XML 文档(使用 DOM API)并相应地重新安排,这样现在文档将根据模式进行验证。
了解此处的 XSOM 是什么很重要 - 它是一个 java API,表示 XML 模式中包含的信息,不是我的实例文档中包含的信息。
我不想做的是从模式生成代码,因为模式在构建时是未知的。此外,XSLT 没有用,因为元素的正确排序仅由模式中包含的数据字典决定。
希望现在已经足够明确了。
最佳答案
我被同样的问题困扰了大约两周。 最后我得到了突破。 这可以使用 JAXB 编码/解码功能来实现。
在 JAXB 编码/解码中,XML 验证是一项可选功能。 因此,在创建 Marshaller 和 UnMarshaller 对象时,我们不调用 setSchema(schema) 方法。 省略此步骤可避免 marshal/unmarshal 的 XML 验证功能。
现在,
- 如果 XML 中没有任何 XSD 规定的强制元素,则忽略它。
- 如果 XSD 中不存在的任何标记在 XML 中存在,则不会抛出错误,并且在编码/解码后获得的新 XML 中也不存在。
- 如果元素不按顺序,它们将重新排序。这是由我们在创建 JAXBContext 时传递的 JAXB 生成的 POJO 完成的。
- 如果某个元素错位在其他标记内,则在新 XML 中将忽略该元素。编码/解码时不会抛出任何错误。
public class JAXBSequenceUtil {
public static void main(String[] args) throws JAXBException, IOException {
String xml = FileUtils.readFileToString(new File(
"./conf/out/Response_103_1015700001&^&IOF.xml"));
System.out.println("Before marshalling : \n" + xml);
String sequencedXml = correctSequence(xml,
"org.acord.standards.life._2");
System.out.println("After marshalling : \n" + sequencedXml);
}
/**
* @param xml
* - XML string to be corrected for sequence.
* @param jaxbPackage
* - package containing JAXB generated classes using XSD.
* @return String - xml with corrected sequence
* @throws JAXBException
*/
public static String correctSequence(String xml, String jaxbPackage)
throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(jaxbPackage);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Object txLifeType = unmarshaller.unmarshal(new InputSource(
new StringReader(xml)));
System.out.println(txLifeType);
StringWriter stringWriter = new StringWriter();
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.marshal(txLifeType, stringWriter);
return stringWriter.toString();
}
}
关于java - 使用模式根据模式重新排序 XML 文档的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1435452/