Gar*_*owe 25 java xml spring jaxb
[根据理解进展重编辑]
是否有可能让Spring Jaxb2Marshaller使用一组自定义的名称空间前缀(或者至少尊重模式文件/注释中给出的名称空间前缀),而不必使用NamespacePrefixMapper的扩展名?
我们的想法是让一个类与另一个类具有"has"关系,而另一个类又包含具有不同命名空间的属性.为了更好地说明这一点,请考虑以下使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
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";
}
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
运行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>
Run Code Online (Sandbox Code Playgroud)
而我想要的是:
<?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>
Run Code Online (Sandbox Code Playgroud)
一旦这部分工作,那么问题就转移到在Spring中配置Jaxb2Marshaller(Spring 2.5.6,spring-oxm-tiger-1.5.6提供Jaxb2Marshaller),以便通过简单的上下文配置提供相同的功能.调用marshal().
感谢您对此问题的持续关注!
Gar*_*owe 12
[提供JAXB-RI替代方案的一些编辑在本文末尾]
经过多次努力之后,我终于不得不接受了我的环境(Windows XP上的JDK1.6.0_12和Mac Leopard上的JDK1.6.0_20)我不能在不诉诸NamespacePrefixMapper的邪恶的情况下完成这项工作.为什么这是邪恶的?因为它强制依赖生产代码中的内部JVM类.这些类不构成JVM和代码之间可靠接口的一部分(即它们在JVM的更新之间发生变化).
在我看来,Sun应该解决这个问题,或者有更深入了解的人可以添加这个答案 - 请做!
继续.因为NamespacePrefixMapper不应该在JVM之外使用,所以它不包含在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>
Run Code Online (Sandbox Code Playgroud)
注意到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>
Run Code Online (Sandbox Code Playgroud)
什么是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"/>
Run Code Online (Sandbox Code Playgroud)
然后我的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 "";
}
}
}
Run Code Online (Sandbox Code Playgroud)
那就是它.我希望这可以帮助别人避免我经历的痛苦.哦,顺便说一下,如果你在Jetty中使用上面的邪恶方法,你可能会遇到以下异常:
java.lang.IllegalAccessError:class sun.reflect.GeneratedConstructorAccessor23无法访问其超类sun.reflect.ConstructorAccessorImpl
祝你好运排序.线索:您的Web服务器的bootclasspath中的rt.jar.
[显示JAXB-RI(参考实现)方法的额外编辑]
如果您能够将JAXB-RI库引入代码中,则可以进行以下修改以获得相同的效果:
主要:
// Add a new property that implies external access
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new MyNamespacePrefixMapper());
Run Code Online (Sandbox Code Playgroud)
MyNamespacePrefixMapper:
// Change the import to this
import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
Run Code Online (Sandbox Code Playgroud)
从/ lib文件夹中的JAXB-RI下载(跳过许可证箍之后)添加以下JAR:
jaxb-impl.jar
Run Code Online (Sandbox Code Playgroud)
运行Main.main()会产生所需的输出.
(重编辑的回复)
我相信代码中的问题是由于某些命名空间URI不匹配造成的.有时您使用" http://www.example.org/abc ",有时使用"www.example.org/abc".以下应该做的伎俩:
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);
System.out.println(jc);
RootElement re = new RootElement();
re.childElementWithXlink = new ChildElementWithXlink();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(re, System.out);
}
}
Run Code Online (Sandbox Code Playgroud)
RootElement.java
package org.example.domain;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(namespace="http://www.example.org/abc", name="Root_Element")
public class RootElement {
@XmlElement(namespace = "http://www.example.org/abc")
public ChildElementWithXlink childElementWithXlink;
}
Run Code Online (Sandbox Code Playgroud)
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="http://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";
}
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
现在运行Main.main()给出以下输出:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<abc:Root_Element xmlns:abc="http://www.example.org/abc" xmlns:xlink="http://www.w3.org/1999/xlink">
<abc:childElementWithXlink xlink:href="http://www.example.org"/>
</abc:Root_Element>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
50446 次 |
| 最近记录: |