[随着理解的进展进行大量编辑]
是否有可能让Spring
Jaxb2Marshaller使用一组自定义的名称空间前缀(或至少尊重模式文件/注释中给出的名称空间)而不必使用NamespacePrefixMapper的扩展?
想法是让一个类与另一个类具有“具有”关系,而另一个类又包含一个具有不同名称空间的属性。为了更好地说明这一点,请考虑以下使用JDK1.6.0_12的项目大纲(我可以使用最新的工作大纲)。我在org.example.domain包中包含以下内容:
Main.java:
package org.example.domain;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class Main {
public static void main(String[] args) throws JAXBException {
JAXBContext jc = JAXBContext.newInstance(RootElement.class);
RootElement re = new RootElement();
re.childElementWithXlink = new ChildElementWithXlink();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(re, System.out);
}
}
RootElement.java:
package org.example.domain;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(namespace = "www.example.org/abc", name="Root_Element")
public class RootElement {
@XmlElement(namespace = "www.example.org/abc")
public ChildElementWithXlink childElementWithXlink;
}
ChildElementWithXLink.java:
package org.example.domain;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
@XmlRootElement(namespace="www.example.org/abc", name="Child_Element_With_XLink")
public class ChildElementWithXlink {
@XmlAttribute(namespace = "http://www.w3.org/1999/xlink")
@XmlSchemaType(namespace = "http://www.w3.org/1999/xlink", name = "anyURI")
private String href="http://www.example.org";
}
package-info.java:
@javax.xml.bind.annotation.XmlSchema(
namespace = "http://www.example.org/abc",
xmlns = {
@javax.xml.bind.annotation.XmlNs(prefix = "abc", namespaceURI ="http://www.example.org/abc"),
@javax.xml.bind.annotation.XmlNs(prefix = "xlink", namespaceURI = "http://www.w3.org/1999/xlink")
},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.example.domain;
运行Main.main()给出以下输出:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:Root_Element xmlns:ns1="http://www.w3.org/1999/xlink" xmlns:ns2="www.example.org/abc">
<ns2:childElementWithXlink ns1:href="http://www.example.org"/>
</ns2:Root_Element>
而我想要的是:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<abc:Root_Element xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:abc="www.example.org/abc">
<abc:childElementWithXlink xlink:href="http://www.example.org"/>
</abc:Root_Element>
一旦这部分工作了,问题就会转移到在Spring中配置Jaxb2Marshaller(Spring 2.5.6,其中spring-oxm-
tiger-1.5.6提供Jaxb2Marshaller),以便通过简单的上下文配置提供相同的功能。调用marshal()。
感谢您一直以来对这个问题的关注!
[提供JAXB-RI替代品的一些编辑在本文的结尾]
在花了很多力气之后,我终于不得不接受针对我的环境(在Windows XP上为JDK1.6.0_12,在Mac
Leopard上为JDK1.6.0_20),我只是在不诉诸于NamespacePrefixMapper这个邪恶的前提下才能完成这项工作。为什么它是邪恶的?因为它强制您的生产代码中依赖内部JVM类。这些类不构成JVM与您的代码之间可靠接口的一部分(即,它们在JVM更新之间进行更改)。
我认为Sun应该解决此问题,或者有更深入知识的人可以添加此答案-请这样做!
继续。因为不应在JVM外部使用NamespacePrefixMapper,所以它不包含在javac的标准编译路径(由ct.sym控制的rt.jar的子部分)中。这意味着任何依赖于它的代码都可以在IDE中正常编译,但是在命令行(例如Maven或Ant)失败。为了克服这个问题,必须在构建中显式包含rt.jar文件,即使在路径中包含空格的情况下,Windows似乎也会遇到麻烦。
如果您处于这个位置,那么以下是Maven片段,它将帮助您摆脱麻烦:
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.1.9</version>
<scope>system</scope>
<!-- Windows will not find rt.jar if it is in a path with spaces -->
<systemPath>C:/temp/rt.jar</systemPath>
</dependency>
注意rt.jar到一个奇怪的地方的垃圾硬编码路径。您可以使用{java.home}
/lib/rt.jar的组合来解决此问题,该组合在大多数操作系统上都可以使用,但是由于Windows空间问题,不能保证。是的,您可以使用配置文件并进行相应的激活…
或者,在Ant中,您可以执行以下操作:
<path id="jre.classpath">
<pathelement location="${java.home}\lib" />
</path>
// Add paths for build.classpath and define {src},{target} as usual
<target name="compile" depends="copy-resources">
<mkdir dir="${target}/classes"/>
<javac bootclasspathref="jre.classpath" includejavaruntime="yes" debug="on" srcdir="${src}" destdir="${target}/classes" includes="**/*">
<classpath refid="build.classpath"/>
</javac>
</target>
以及Jaxb2Marshaller Spring的配置是什么?好的,这里是我自己的NamespacePrefixMapper:
弹簧:
<!-- JAXB2 marshalling (domain objects annotated with JAXB2 meta data) -->
<bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPaths">
<list>
<value>org.example.domain</value>
</list>
</property>
<property name="marshallerProperties">
<map>
<!-- Good for JDK1.6.0_6+, lose 'internal' for earlier releases - see why it's evil? -->
<entry key="com.sun.xml.internal.bind.namespacePrefixMapper" value-ref="myCapabilitiesNamespacePrefixMapper"/>
<entry key="jaxb.formatted.output"><value type="boolean">true</value></entry>
</map>
</property>
</bean>
<!-- Namespace mapping prefix (ns1->abc, ns2->xlink etc) -->
<bean id="myNamespacePrefixMapper" class="org.example.MyNamespacePrefixMapper"/>
然后是我的NamespacePrefixMapper代码:
public class MyNamespacePrefixMapper extends NamespacePrefixMapper {
public String getPreferredPrefix(String namespaceUri,
String suggestion,
boolean requirePrefix) {
if (requirePrefix) {
if ("http://www.example.org/abc".equals(namespaceUri)) {
return "abc";
}
if ("http://www.w3.org/1999/xlink".equals(namespaceUri)) {
return "xlink";
}
return suggestion;
} else {
return "";
}
}
}
好吧。我希望这可以帮助某人避免我经历的痛苦。哦,顺便说一句,如果您在Jetty中使用上述邪恶方法,则可能会遇到以下异常:
java.lang.IllegalAccessError:类sun.reflect.GeneratedConstructorAccessor23无法访问其超类sun.reflect.ConstructorAccessorImpl
真是太幸运了,整理出一个。提示:Web服务器的引导类路径中的rt.jar。
[进行额外编辑以显示JAXB-RI(参考实现)方法]
如果您能够在代码中引入JAXB-RI库,则可以进行以下修改以获得相同的效果:
主要:
// Add a new property that implies external access
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new MyNamespacePrefixMapper());
MyNamespacePrefixMapper:
// Change the import to this
import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
从/ lib文件夹中添加JAXB-RI下载中的以下JAR(跳过许可环后):
jaxb-impl.jar
运行Main.main()会产生所需的输出。
我想知道是否有一种方法来强制JAXB创建与XSD模式相同的名称空间前缀。即,即使我从一个包含xmlns:cts=“http://cts.com”的模式创建JAXB类,在封送类之后,我得到一个具有xmlns:ns1前缀的XML。我知道我可以通过使用NamespacePrefixMapper类来重写这些,但是为什么我需要在我的XSD明确定义了默认前缀的情况下手动执行此操作呢?在我当前的XML中有大量的
问题内容: 我需要为元素添加名称空间定义,因为使用apache xmlbean生成xml时不会添加元素。如何使用xmlbeans API做到这一点? 问题答案: 我已经找到问题的答案。就是这样。
我正在尝试为我的Laravel(5.2)API项目设置单元测试。在使用单元测试之前,我想为它们定义一个自定义名称空间,因此我创建了文件。像这样: 然后,我创建了一个文件夹下的文件夹,并将我的单元测试放在该文件夹与以下命名空间: 现在,当我想运行单元测试时,我得到以下错误: 所以基本上,Laravel认为在Test命名空间中可以找到类,而不是Laravel的命名空间。 我还在文件: 我也尝试过运行这
我有一个具有WSDL定义的非常基本的WCF服务,如下所示: 我想添加名称空间xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance“根据定义,但我不知道在哪里以及如何。 如何添加该名称空间?非常感谢。
问题内容: 除了包级别注释外,还有其他方法可以使用注释来控制自定义名称空间前缀。 可以在元素级别完成吗?也可能有一个带有多个前缀的名称空间吗? 问题答案: 您实际上想做什么?为什么名称空间前缀对您很重要? 对于命名空间前缀,没有标准的元素级注释。 我知道的控制名称空间前缀的选项是: 你已经提到过。 提供习俗。 XML的低级处理(例如,在StAX,SAX或DOM级别)。 我也可以想象: / 通常使用
例如,一个XML属性值是,但名称空间前缀“repository”从未在数据集中定义。(不要紧,提供商的最佳实践建议定义它!) 所以当我去解封一个示例集时,具有指定前缀的QName属性(在我上面的示例中为“Repository”)是空的!所以看起来JAXB正在“抛出”那些具有未定义名称空间前缀的属性QName值。我很惊讶,它甚至没有保留当地的名字。 理想情况下,我希望保持该值原样,但看起来我无法在绑