java - 使用模式根据模式重新排序 XML 文档的元素

标签 java xml xsd xsom

假设我有一个 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 验证功能。

现在,

  1. 如果 XML 中没有任何 XSD 规定的强制元素,则忽略它。
  2. 如果 XSD 中不存在的任何标记在 XML 中存在,则不会抛出错误,并且在编码/解码后获得的新 XML 中也不存在。
  3. 如果元素不按顺序,它们将重新排序。这是由我们在创建 JAXBContext 时传递的 JAXB 生成的 POJO 完成的。
  4. 如果某个元素错位在其他标记内,则在新 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/

相关文章:

xml - xslt 识别转换后值未转换

python - 使用递归使用 Python 解析 Xml。返回值有问题

java - 解析内联 XML 架构 (Xerces for Java)

xml - cvc-complex-type.2.3 : Element 'group' cannot have character [children], 因为类型的内容类型是仅元素

java - 为移动正方形设置边框

java - 当方法返回 null 时会发生什么

java - 诺基亚 S60 Java SDK?

c# - Excel XML 电子表格 CSHTML

Java 外部类加载 ClassDefNotFoundError

xml - XSD 中的 Ref 属性或 Type 属性