RESTeasy/JAXB;如何避免将命名空间添加到中的元素中标签? (JAXB 中的列表<元素>)元素>
我将在这里尽可能简化我的类和输出,但基本上我想要添加一个 org.w3c.dom.Element
(代表此中的原子链接) case) 到我要返回的 JAXB 对象。 JAXB 类看起来像这样:
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
import org.w3c.dom.Element;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "People", namespace = "main", propOrder = {
"any",
"persons"
})
public class People {
@XmlAnyElement
protected List<Element> any;
@XmlElement(name = "person", namespace = "main")
protected List<Person> persons;
[...]
}
我正在使用我创建的模板创建元素,如下所示:(
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
public class ElementGen {
public Element getTemplate() throws DOMException, SAXException, ParserConfigurationException {
final SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
final Schema schema = sf.newSchema(new StreamSource(
Thread.currentThread().getContextClassLoader().getResourceAsStream(ATOM_XSD)));
final DocumentBuilderFactory docBuilder = DocumentBuilderFactory.newInstance();
docBuilder.setSchema(schema);
final Document doc = docBuilder.newDocumentBuilder().newDocument();
linkTemplate = doc.createElementNS(ATOM_NAMESPACE, ATOM_LINK);
return linkTemplate;
}
}
这实际上并不是该类的样子,我只是想让它尽可能容易地编译一些东西来测试它,而无需所有外部混乱)。
然后,我使用 linkTemplate.cloneNode(false);
克隆该模板
现在,这一切都有效,因为它返回 xml,但奇怪的是,我返回的 xml 附加了额外的命名空间:
<atom:link xmlns:ns3="main" xmlns="" href="href" rel="rel"/>
如果我添加 < code>linkTemplate.setAttribute("xmlns", null); “xmlns:ns3”命名空间消失,我得到:
<atom:link xmlns="" href="href" rel="rel"/>
但似乎没有办法删除该 xmlns=""。我是否以错误的方式创建了元素?或者也许还有其他问题?我很不知道为什么要添加这些,所以任何帮助/解释将不胜感激。
编辑:我相信它一定与我用于生成元素的文档的命名空间有关,但我不确定如何修复它。有没有办法在文档上设置(XML)targetNamespace?
编辑2:我不确定它是否添加了对任何人有用的东西,但经过更多实验,我发现 linkTemplate.setAttribute("xmlns:" + everything, null);
具有创建与 xmlns:[anything]=""
链接并删除否则会生成的任何其他内容。
编辑 3:用于生成 JAXB 对象的 xsd 的相关位是:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0"
xmlns="main"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:atom="http://www.w3.org/2005/Atom"
targetNamespace="main"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:complexType name="People">
<xs:sequence>
<xs:any namespace="##other" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="person" type="Person" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
[attributes]
</xs:complexType>
[other types etc.]
I'm going to simplify my classes and output as best I can here, but basically what I'm after is I want to add an org.w3c.dom.Element
(representing an atom link in this case) to a JAXB object I'm returning. The JAXB Class looks something like:
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
import org.w3c.dom.Element;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "People", namespace = "main", propOrder = {
"any",
"persons"
})
public class People {
@XmlAnyElement
protected List<Element> any;
@XmlElement(name = "person", namespace = "main")
protected List<Person> persons;
[...]
}
I'm creating the Element using a template I create like this:
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
public class ElementGen {
public Element getTemplate() throws DOMException, SAXException, ParserConfigurationException {
final SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
final Schema schema = sf.newSchema(new StreamSource(
Thread.currentThread().getContextClassLoader().getResourceAsStream(ATOM_XSD)));
final DocumentBuilderFactory docBuilder = DocumentBuilderFactory.newInstance();
docBuilder.setSchema(schema);
final Document doc = docBuilder.newDocumentBuilder().newDocument();
linkTemplate = doc.createElementNS(ATOM_NAMESPACE, ATOM_LINK);
return linkTemplate;
}
}
(That's not actually what the class looks like, I'm just trying to make it as easy as possible to compile something to test it without all the external mess).
I then clone that template using linkTemplate.cloneNode(false);
Now this all works in that it returns xml, but the odd thing is that the xml I get back has additional namespaces attached:
<atom:link xmlns:ns3="main" xmlns="" href="href" rel="rel"/>
If I add linkTemplate.setAttribute("xmlns", null);
the "xmlns:ns3" namespace disappears and I get:
<atom:link xmlns="" href="href" rel="rel"/>
But there seems to be no way of removing that xmlns="". Am I creating the Element in the wrong way? Or perhaps something else is going wrong? I'm rather at a loss as to why it's adding these at all so any help/explanation would be appreciated.
Edit: I believe it must be related to the namespace of the document I use for generating the Element, but I'm not sure how to fix it. Is there any way of setting the (XML) targetNamespace on the document?
Edit 2: I'm not sure if it adds anything useful for anyone, but with more experimenting I found that linkTemplate.setAttribute("xmlns:" + anything, null);
has the effect of creating a link with xmlns:[anything]=""
and removing any others that would have otherwise been generated.
Edit 3: The relevant bits of the xsd used to generate the JAXB objects is:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0"
xmlns="main"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:atom="http://www.w3.org/2005/Atom"
targetNamespace="main"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:complexType name="People">
<xs:sequence>
<xs:any namespace="##other" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="person" type="Person" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
[attributes]
</xs:complexType>
[other types etc.]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
ATOM_LINK = "link" 的值是?如果是这样,它应该是“atom:link”,并删除 setPrefix() 调用。
is the value of ATOM_LINK = "link"? if so, it should be "atom:link", and remove the setPrefix() call.
我相信问题在于您创建的 DocumentBuilderFactory 应该具有名称空间感知能力。
如果您发现自己直接操作
xmlns
属性,则某些东西是错误的。I believe the problem is that the
DocumentBuilderFactory
you aere creating should be name space aware.If you find yourself manipulating
xmlns
attribute directly, somethibng is wrong.您是否尝试过将 elementFormDefault 设置为“UNqualified”?
Have you tried setting your elementFormDefault to "UNqualified" ?
由于这里的建议都不适合我,所以我决定走另一条路。最后,我最终用我自己的监听器覆盖了 RESTEasy 添加到 Marshaller 的监听器。然后,此侦听器调用 RESTEasy 侦听器(如果存在),然后在 RESTServiceDiscovery 字段上手动添加链接(您必须使用反射获取此字段,并在获取对象之前使用 field.setAccessible(true) 关闭访问检查) 。
Since none of the suggestions here have worked for me I've decided to go a different route. In the end I ended up overwriting the Listener RESTEasy adds to the Marshaller with a Listener of my own. This Listener then calls the RESTEasy listener (if it was present), before adding the links manually on the RESTServiceDiscovery field (you have to get this field using reflection, and turn off access checking with field.setAccessible(true) before getting the object).