如何避免 xmlns=""要添加到操纵的 XML 根元素? [英] How to avoid xmlns="" to be added to a manipulated XML root element?

查看:32
本文介绍了如何避免 xmlns=""要添加到操纵的 XML 根元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在更改 persistence.xmljta-data-source 值,如下所示:

I'm changing the jta-data-source value of a persistence.xml as follows:

JavaArchive jarArchive = Maven.configureResolver().workOffline().resolve("richtercloud:project1-jar:jar:1.0-SNAPSHOT").withoutTransitivity().asSingle(JavaArchive.class);
Node persistenceXml = jarArchive.get("META-INF/persistence.xml");
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document persistenceXmlDocument = documentBuilder.parse(persistenceXml.getAsset().openStream());
    //asked
    //https://stackoverflow.com/questions/46771622/how-to-create-a-shrinkwrap-persistencedescriptor-from-an-existing-persistence-xm
    //for how to manipulate persistence.xml more easily with
    //ShrinkWrap's PersistenceDescriptor
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("//persistence-unit/jta-data-source");
org.w3c.dom.Node persistenceXmlDataSourceNode = (org.w3c.dom.Node) expr.evaluate(persistenceXmlDocument,
        XPathConstants.NODE);
persistenceXmlDataSourceNode.setTextContent("jdbc/project1-test-db");

TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
//transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
//was there before, but unclear why
StringWriter writer = new StringWriter();
transformer.transform(new DOMSource(persistenceXmlDocument), new StreamResult(writer));
String persistenceUnit = writer.toString();

(由于 如何创建 ShrinkWrap来自现有 persistence.xml 的 PersistenceDescriptor? 尚未得到答复).

(since How to create a ShrinkWrap PersistenceDescriptor from an existing persistence.xml? has not been answered, yet).

这很好用,除了在根 persistence 元素下添加到 persistence-unitxmlns="" 属性似乎原因:

That works fine, except for a xmlns="" attribute added to the persistence-unit under the root persistence element which seems to cause:

java.io.IOException: org.xml.sax.SAXParseException;行号:2;列数:108;存档 [project1-jar-1.0-SNAPSHOT.jar] 中的部署描述符文件 META-INF/persistence.xml.cvc-complex-type.2.4.a:发现以元素persistence-unit"开头的无效内容.'{"http://xmlns.jcp.org/xml/ns/persistence":persistence-unit}'.

java.io.IOException: org.xml.sax.SAXParseException; lineNumber: 2; columnNumber: 108; Deployment descriptor file META-INF/persistence.xml in archive [project1-jar-1.0-SNAPSHOT.jar]. cvc-complex-type.2.4.a: Invalid content was found starting with element 'persistence-unit'. One of '{"http://xmlns.jcp.org/xml/ns/persistence":persistence-unit}' is expected.

我不坚持使用 Transformer 和相关类的想法.

I'm not adhering to the idea to use Transformer and related classes.

推荐答案

不知道为什么我不能在 Java SE 中重现这个,但问题是 javax.xml.parsers.DocumentBuilder 通过default 不知道命名空间,因此在操作文档期间命名空间信息会丢失,因此 Transformer 添加一个空的 xmlns.

No idea why I can't reproduce this in Java SE, but the problem is that javax.xml.parsers.DocumentBuilder by default isn't namespace aware so that the namespace information gets lost during manipulation of the document and consequently an empty xmlns is added by Transformer.

既然 DocumentBuilder 是命名空间感知的,XPath 解析不起作用并且查询返回 null,请参阅 XPath 为节点"返回空值当 isNameSpaceAware 和 isValidating 为true"时,有关 XPath 名称空间感知问题的详细描述和更多详细信息(我无法获得构建自定义 NamespaceContext 的解决方案才能工作).

Now that DocumentBuilder is namespace aware, XPath resolution doesn't work and queries return null, see XPath returning null for "Node" when isNameSpaceAware and isValidating are "true" for a detailed description and more details on the XPath namespace awareness issue (I couldn't get the solution to build a custom NamespaceContext to work).

为了避免这种情况,我最终调整了我的 XPath 查询以使用 local-name 函数,如 如何在使用 XPath 选择 XML 节点时忽略命名空间.即 //*[local-name()='jta-data-source'].

In order to avoid this I finally adjusted my XPath query to use the local-name function as described at How to ignore namespace when selecting XML nodes with XPath. i.e. //*[local-name()='jta-data-source'].

仍然需要使用 Document.createElementNS 而不是 createElement 以避免在新创建的元素上出现空的 xmlns 属性,参见 空的默认 XML 命名空间 xmlns="";正在添加属性? 解释一下.

It's still necessary to use Document.createElementNS instead of createElement in order to avoid empty xmlns attribute on newly created elements, see Empty default XML namespace xmlns="" attribute being added? for an explanation.

这篇关于如何避免 xmlns=""要添加到操纵的 XML 根元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆