代码之家  ›  专栏  ›  技术社区  ›  user1884155

XML命名空间因DocumentBuilder/Transformer的不同实现而不同

  •  0
  • user1884155  · 技术社区  · 10 年前

    我有两台机器,上面有相同的java代码。代码是关于使用文档生成器构建xml文档,以及使用转换器将该文档转换为字符串。两者都使用 factory.newInstance() :

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    
    TransformerFactory tff = TransformerFactory.newInstance();
    Transformer tf = tff.newTransformer();
    

    然而,我注意到他们的行为不同。一台1机器,在文档中正确插入节点,将空名称空间转换为名称等于空字符串的名称空间。在另一台机器上,这不会发生,也不会插入任何名称空间,元素使用父元素的名称空间。

    所以我比较了工厂和生成器/转换器的实际类/类加载器,它们确实不同。以下是正确输出的日志文件:

    DocumentBuilderFactory class name:      com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
    DocumentBuilderFactory class loader:        null
    DocumentBuilderFactory class package:       package com.sun.org.apache.xerces.internal.jaxp, Java Platform API Specification, version 1.7
    
    DocumentBuilder class name:             com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl
    DocumentBuilder class loader:           null
    DocumentBuilder class package:      package com.sun.org.apache.xerces.internal.jaxp, Java Platform API Specification, version 1.7
    
    TransformerFactory class name:      com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
    TransformerFactory class loader:        null
    transformerFactory class package:       package com.sun.org.apache.xalan.internal.xsltc.trax, Java Platform API Specification, version 1.7
    
    Transformer class name:             com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl
    Transformer class loader:           null
    Transformer class package:          package com.sun.org.apache.xerces.internal.jaxp, Java Platform API Specification, version 1.7
    

    下面是错误输出的日志:

    DocumentBuilderFactory class name:      org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
    DocumentBuilderFactory class loader:        sun.misc.Launcher$AppClassLoader@2ff40e1f
    DocumentBuilderFactory class package:       package org.apache.xerces.jaxp
    
    DocumentBuilder class name:             org.apache.xerces.jaxp.DocumentBuilderImpl
    DocumentBuilder class loader:           sun.misc.Launcher$AppClassLoader@2ff40e1f
    DocumentBuilder class package:      package org.apache.xerces.jaxp
    
    TransformerFactory class name:      org.apache.xalan.processor.TransformerFactoryImpl
    TransformerFactory class loader:        sun.misc.Launcher$AppClassLoader@2ff40e1f
    transformerFactory class package:       package org.apache.xalan.processor
    
    Transformer class name:             org.apache.xalan.transformer.TransformerIdentityImpl
    Transformer class loader:           sun.misc.Launcher$AppClassLoader@2ff40e1f
    Transformer class package:          package org.apache.xerces.jaxp
    

    我想告诉第二台机器要像第一台机器一样工作,但我不熟悉cloassloader是如何工作的。有人能给我详细的信息吗

    1) 为什么会有区别,类加载在这个上下文中意味着什么? 2) 如何更改机器#2的默认行为以使用与机器#1相同的内容?

    1 回复  |  直到 10 年前
        1
  •  1
  •   Michael Kay    10 年前

    这可能是错误的做法。Apache中的Xerces和Xalan版本通常比JDK中的版本更可靠、更健壮、更符合标准。我会尝试将所有内容都转移到Apache版本,并找出在这些情况下为什么您的代码会给出错误的结果,并进行修复。我们需要查看您认为是什么代码给出了错误的结果的详细信息,以告诉您哪个产品实际上是按照规范运行的,哪个产品不是。根据规格选择正确的产品比选择恰好能满足您需求的产品要好得多。

    您可以通过多种方式控制JAXP加载的版本:通过更改类路径上的内容、设置Java系统财产或显式加载选定的版本。如果您查看DocumentBuilderFactory和TransformerFactory等类的Javadoc,它将为您提供非常详细的解释。