首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在保持xsi:类型的同时合并文档

在保持xsi:类型的同时合并文档
EN

Stack Overflow用户
提问于 2011-06-01 08:45:29
回答 6查看 2.2K关注 0票数 5

我有两个包含类似XML文档的文档对象。

代码语言:javascript
复制
<tt:root xmlns:tt="http://myurl.com/">
  <tt:child/>
  <tt:child/>
</tt:root>

另一个是:

代码语言:javascript
复制
<ns1:root xmlns:ns1="http://myurl.com/" xmlns:ns2="http://myotherurl.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ns1:child/>
  <ns1:child xsi:type="ns2:SomeType"/>
</ns1:root>

我需要将它们合并为一个包含一个根元素和四个子元素的文档。问题是,如果我使用document.importNode函数进行合并,它将正确处理除xsi:type元素之外的所有名称空间。所以我得到的结果是:

代码语言:javascript
复制
<tt:root xmlns:tt="http://myurl.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <tt:child/>
  <tt:child/>
  <ns1:child xmlns:ns1="http://myurl.com/"/>
  <ns1:child xmlns:ns1="http://myurl.com/" xsi:type="ns2:SomeType"/>
</tt:root>

如您所见,ns2在xsi:type中使用,但在任何地方都没有定义。有什么自动解决这个问题的方法吗?

谢谢。

添加:

如果这个任务无法使用默认的java库来完成,那么可能还有其他库可以用来完成我的任务吗?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2011-06-08 21:46:32

XQuery的一行可以完成以下工作:构造一个名为上下文根元素的新节点,然后将其子节点与其他文档中的子节点一起导入:

代码语言:javascript
复制
declare variable $other external; element {node-name(*)} {*/*, $other/*/*}

虽然在XQuery中您不能完全控制命名空间节点(至少在XQuery 1.0中是这样),但是它有一个copy-namespaces模式设置,可以用来要求保持名称空间上下文的完整,以防实现在默认情况下保留它。

如果XQuery是一个可行的选项,那么saxon9he.jar可能是您所追求的“神奇的xml库”。

下面是使用s9api API公开一些上下文的示例代码

代码语言:javascript
复制
import javax.xml.parsers.DocumentBuilderFactory;
import net.sf.saxon.s9api.*;
import org.w3c.dom.Document;

...

  Document merge(Document context, Document other) throws Exception
  {
    Processor processor = new Processor(false);
    XQueryExecutable executable = processor.newXQueryCompiler().compile(
      "declare variable $other external; element {node-name(*)} {*/*, $other/*/*}");
    XQueryEvaluator evaluator = executable.load();    
    DocumentBuilder db = processor.newDocumentBuilder();
    evaluator.setContextItem(db.wrap(context));
    evaluator.setExternalVariable(new QName("other"), db.wrap(other));
    Document doc =
      DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
    processor.writeXdmValue(evaluator.evaluate(), new DOMDestination(doc));
    return doc;
  }
票数 1
EN

Stack Overflow用户

发布于 2011-06-01 11:04:47

如果我修复了第二个文件中的命名空间问题(通过绑定"xsi“前缀),并使用下面的代码进行合并,名称空间绑定将保留在输出上;或者至少在这里( Windows 1.6.0_24上的普通Java64位)。

代码语言:javascript
复制
String s1 = "<!-- 1st XML document here -->";
String s2 = "<!-- 2nd XML document here -->";

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware( true );
DocumentBuilder builder = factory.newDocumentBuilder();

Document doc1 = builder.parse( new ByteArrayInputStream( s1.getBytes() ) );
Document doc2 = builder.parse( new ByteArrayInputStream( s2.getBytes() ) );

Element doc1root = ( Element )doc1.getDocumentElement();
Element doc2root = ( Element )doc2.getDocumentElement();

NamedNodeMap atts1 = doc1root.getAttributes();
NamedNodeMap atts2 = doc2root.getAttributes();

for( int i = 0; i < atts1.getLength(); i++ )
{
    String name = atts1.item( i ).getNodeName();
    if( name.startsWith( "xmlns:" ) )
    {
        if( atts2.getNamedItem( name ) == null )
        {
            doc2root.setAttribute( name, atts1.item( i ).getNodeValue() );
        }    
    }    
}

NodeList nl = doc1.getDocumentElement().getChildNodes();
for( int i = 0; i < nl.getLength(); i++ )
{
    Node n = nl.item( i );
    doc2root.appendChild( doc2.importNode( n, true ) );

}

TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
StreamResult streamResult = new StreamResult( System.out );
transformer.transform( new DOMSource( doc2 ), streamResult );
票数 2
EN

Stack Overflow用户

发布于 2011-06-06 09:01:01

这里的问题是在属性值中使用名称空间前缀;在创建命名空间标准时从未考虑到的问题,以及一些常见的Java /XML工具无法轻松处理的问题。但是,你可以通过

  1. 在合并之前,将xsi:type="prefix:value"的每个实例替换为xsi:type="{namespace}value"。通过这样做,您不依赖于前缀映射。在您的示例中,<xsi:type="ns2:SomeType"将变成xsi:type="{http://myotherurl.com/}SomeType"
  2. 合并文件。
  3. 在结果文档中,在步骤1中反转替换,必须仔细管理前缀映射以避免冲突;可能需要创建新的映射。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6198485

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档