我在java项目上工作,我需要从XML文件中读取一些对象,进行一些处理,这将改变对象的属性,然后将Object写入另一个XML文件。为此,我使用JAXB的编组和解组功能,每个都在一个方法中,如下所示:
private MyObject unmarshallXMLFile(String file) {
MyObject t=null;
try {
jc = JAXBContext.newInstance("foo.bar");
Unmarshaller unmarshaller = jc.createUnmarshaller();
SchemaFactory sf = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
unmarshaller.setSchema(sf.newSchema(new File("MySchema.xsd")));
t = (Task) unmarshaller.unmarshal(new File(file));
} catch (JAXBException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
return t;
}
private void marshallXMLFile(String file) {
task.setReplay(Boolean.TRUE);
Marshaller marshaller;
try {
marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, new Boolean(true));
marshaller.marshal(task, new FileOutputStream(file));
} catch (JAXBException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
问题是自动生成的名称空间前缀(如ns2或ns3)一直出现在输出文件中,然后当我想使用unmarshallXMLFile方法重用这些文件时(我将在稍后再次使用输出文件作为输入)它不会针对模式进行验证,并抛出org.xml.sax.SAXParseException。这是我写的文件:
XML Schema:MySchema.xsd
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/MySchema"
xmlns:spm="http://www.example.org/MySchema"
elementFormDefault="qualified"
attributeFormDefault="qualified">
<element name="task" >
<complexType>
<sequence>
<element name="replay" type="boolean" default="false"/>
<element name="threads" type="spm:spThread" maxOccurs="unbounded" minOccurs="1" />
</sequence>
</complexType>
</element>
<complexType name="spThread">
<sequence>
<element name="SPThreadID" type="int" />
<element name="durtime" minOccurs="0" default="0">
<simpleType>
<restriction base="int">
<minInclusive value="0" />
</restriction>
</simpleType>
</element>
<element name="minexecutions" minOccurs="0" default="0">
<simpleType>
<restriction base="int">
<minInclusive value="0" />
</restriction>
</simpleType>
</element>
<element name="numThreads" type="int" />
<element name="procedures" type="spm:procedure" minOccurs="1"
maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="procedure">
<sequence>
<element name="id" type="int" minOccurs="1" />
<element name="name" type="string" minOccurs="1" />
<element name="weight" minOccurs="1">
<simpleType>
<restriction base="int">
<minInclusive value="0" />
<maxInclusive value="100" />
</restriction>
</simpleType>
</element>
<element name="parameterPool" type="spm:parameter" nillable="true"
minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="parameter">
<sequence>
<element name="name" type="string" minOccurs="1" />
<element name="dataType" type="spm:parameterDataType" default="integer"/>
<element name="parmType" type="spm:parameterType" default="in"
minOccurs="0" />
<element name="minValue" type="string"/>
<element name="maxValue" type="string"/>
<element name="value" type="string"/>
</sequence>
</complexType>
<simpleType name="parameterDataType">
<restriction base="string">
<enumeration value="integer" />
<enumeration value="varchar" />
<enumeration value="char" />
</restriction>
</simpleType>
<simpleType name="parameterType">
<restriction base="string">
<enumeration value="in" />
<enumeration value="out" />
<enumeration value="in_out" />
</restriction>
</simpleType>
</schema>
输入文件:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<task xmlns="http://www.example.org/MySchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/MySchema MySchema.xsd ">
<replay>true</replay>
<threads>
<SPThreadID>0</SPThreadID>
<durtime>10</durtime>
<minexecutions>2</minexecutions>
<numThreads>3</numThreads>
<procedures>
<id>1</id>
<name>run</name>
<weight>15</weight>
<parameterPool>
<name>energy</name>
<dataType>integer</dataType>
<parmType>in</parmType>
<minValue>10</minValue>
<maxValue>50</maxValue>
<value>11</value>
</parameterPool>
<parameterPool>
<name>speed</name>
<dataType>integer</dataType>
<parmType>in</parmType>
<minValue>12</minValue>
<maxValue>80</maxValue>
<value>13</value>
</parameterPool>
</procedures>
</threads>
</task>
输出文件(无需任何处理:只需使用前面提到的方法进行解组和编组)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:task xmlns="http://www.example.org/MySchema" xmlns:ns2="http://www.example.org/MySchema.xsd">
<replay>true</replay>
<threads>
<SPThreadID>0</SPThreadID>
<durtime>10</durtime>
<minexecutions>2</minexecutions>
<numThreads>3</numThreads>
<procedures>
<id>1</id>
<name>run</name>
<weight>15</weight>
<parameterPool>
<name>energy</name>
<dataType>integer</dataType>
<parmType>in</parmType>
<minValue>10</minValue>
<maxValue>50</maxValue>
<value>11</value>
</parameterPool>
<parameterPool>
<name>speed</name>
<dataType>integer</dataType>
<parmType>in</parmType>
<minValue>12</minValue>
<maxValue>80</maxValue>
<value>13</value>
</parameterPool>
</procedures>
</threads>
</ns2:task>
异常(再次使用输出文件作为输入时):
javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException: cvc-elt.1: The declaration of the element'ns3:task' could not be found.]
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:326)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:500)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:206)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:175)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:148)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:153)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:180)
at Test.main(Test.java:48)
Caused by: org.xml.sax.SAXParseException: cvc-elt.1: The declaration of the element'ns3:task' could not be found.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
at org.apache.xerces.util.ErrorHandlerWrapper.error(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.handleStartElement(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.startElement(Unknown Source)
at org.apache.xerces.jaxp.validation.XMLSchemaValidatorHandler.startElement(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.startElement(ValidatingUnmarshaller.java:85)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:113)
at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl$NSContentDispatcher.scanRootElementHook(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:202)
... 6 more
我一直在阅读有关这个主题的内容,并尝试了大量相关的答案,但似乎都没有删除前缀。我通过这个guide,但我正在使用的jaxb版本不支持NamespacePrefixMapper。我尝试使用here所述的注释来配置前缀,但这样做无效。
也许有办法摆脱这个命名空间前缀:我发现的所有论坛,答案和讨论都谈到了自定义这个前缀,我只是想摆脱它们。但不知何故,它让我觉得我在输入文件和架构中都缺少一些东西。他们写得好吗?我会说有问题,因为这是我第一次在这个深度使用xml和xsd,而我所做的只是基于我在网上找到的东西。有关改进xml和xsd设计的任何提示都将受到高度赞赏
我应该在输入文件或模式中使用某种前缀,以便JAXB框架在编组时不会生成随机前缀吗?
提前谢谢,我希望你们能帮助我。-
非常感谢您的回答。这样我就可以使用NamespacePrefixMapper。但是,当我使用它时,我的代码在运行时不断抛出异常:
Exception in thread "main" java.util.MissingResourceException: Can't find bundle for base name javax.xml.bind.Messages, locale de_DE
at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:863)
at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:832)
at java.util.ResourceBundle.getBundle(ResourceBundle.java:576)
at javax.xml.bind.Messages.format(Messages.java:47)
at javax.xml.bind.Messages.format(Messages.java:36)
at javax.xml.bind.PropertyException.<init>(PropertyException.java:99)
at javax.xml.bind.helpers.AbstractMarshallerImpl.setProperty(AbstractMarshallerImpl.java:349)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.setProperty(MarshallerImpl.java:527)
at Test.main(Test.java:95)
我发现它必须对.properties文件做一些事情:我没有使用类似的东西,我没有改变任何东西。
答案 0 :(得分:12)
不是在每个元素中指定@XmlElement
的命名空间属性,而是在包级别进行注释更简单。
您可以通过在要注释的包下面创建文件package-info.java
来实现此目的。
例如,如果要注释包org.example
,则必须将名为package-info.java
的文件放在具有以下内容的目录org / example中:
@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.example.org/StoredProceduresSchema", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.example;
重要的是要注意,您必须注释包含您计划编组或被其引用的类的每个包。
希望这会有所帮助:)
答案 1 :(得分:3)
尝试使用NamespacePrefixMapper
:
NamespacePrefixMapper mapper = new NamespacePrefixMapper() {
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
return "";
}
};
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", mapper);
答案 2 :(得分:3)
嗯,经过一些研究,我尝试在我尝试序列化的类的每个属性上使用@XMLElement
标记,清楚地指定我的命名空间是什么,并在每个属性上使用相同的:
@XmlElement(required = true, name="myObjectPool", namespace="http://www.example.org/StoredProceduresSchema")
protected List<MyObject> myObjectPool;
它完美无缺:在编组文件中没有更奇怪的命名空间。
我想感谢他的回答:我也试过了,但我得到了一个奇怪的语言包相关异常。我很高兴这种简单的方法解决了这个问题。
答案 3 :(得分:1)
然后您可能正在使用与引用不同的JAXB实现。阅读本文并重试:http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html(或者如果你很懒:用com.sun.xml.internal.bind.namespacePrefixMapper替换com.sun.xml.bind.namespacePrefixMapper)
答案 4 :(得分:1)
此问题与默认实现JAXB Provider有关。我找到了一个使用不同实现的解决方案:EclipseLink MOXy。
1.在pom.xml
中添加依赖项
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>2.5.0</version>
</dependency>`
2.创建包含以下行的文件jaxb.properties
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
将文件移动到包模型中
3.将package-file.java创建到模型包中@XmlSchema(xmlns = { @XmlNs(prefix = "video", namespaceURI = "http://www.google.com/schemas/sitemap-video/1.1"),
@XmlNs(prefix = "", namespaceURI = "http://www.sitemaps.org/schemas/sitemap/0.9")})
package it.my.sitemap.model;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlSchema;