如何使用JAXB和不同但兼容的上下文来解组XML文档

时间:2011-03-02 23:18:45

标签: xml replace namespaces jaxb

我正在尝试编写一个转换工具,该工具采用旧版XML文档(遵循oldSchema.xsd)并将其转换为新的XML格式(遵循newSchema.xsd)。

也许我说这完全错了,但第一步是创建一个新旧XML文档验证的中间模式。例如,假设我有一个XML文档

<Doc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="old oldSchema.xsd" xmlns="old">

    <OldElement/>
</Doc>

我希望将其转换为

<Doc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="new newSchema.xsd" xmlns="new">

    <NewElement/>
</Doc>

oldSchema.xsd将Doc定义为具有名为OldElement的必需元素的序列。 newSchema.xsd将Doc定义为具有名为NewElement的必需元素的序列。我的中间模式有一个序列,可以选择OldElement或NewElement。

显然,我需要以编程方式处理更多内容。在解组OldElement XML文件之前,我需要将命名空间“old”替换为我的中间命名空间,以便我可以使用用我的中间上下文创建的JAXB实例。

这可能吗?我尝试实施自己的XMLStreamReader,除了XMLInputFactory.newInstance().createXMLStreamReader()之外,所有方法都委托给getNamespaceURI(*)。对于这些,我实现了诸如

之类的东西
public String getNamespaceURI() {
    String existingNS = delegate.getNamespaceURI();
    return subs.get(existingNS) == null ? existingNS : subs.get(existingNS)
}

其中subs将命名空间“old”映射到上面示例中的命名空间“new”。我为XMLStreamReader中的所有getNamespaceURI(*)方法重复了这个。然后我将NamespaceSubstitutionXMLReader的实例传递给unmarshaller.unmarshal(XMLStreamReader)。未编组的对象树具有正确类型的根节点,但其所有子元素都为null。我不太明白为什么这种方法不起作用,但我再次对Unmarshaller的实现完全不熟悉。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

我领导EclipseLink JAXB (MOXy),但如果您想要做的只是转换XML,我建议使用XSLT和javax.xml.transform API。