dom4j 新增节点 自动出现xmlns=""

本文详细介绍了在使用DOM4J操作XML文档时,新增子节点时自动添加xmlns属性的问题,解释了其根本原因,并提供了解决方法。通过案例演示,帮助开发者避免常见错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在写使用dom4j增加元素的子节点和兄弟节点,遇到一个问题:新增的子节点,自带xmlns="" 的属性,导致程序报错。

百度良久,终于找到了解决方法,记录下来,以便后面参考,也提供给其他读者参考。

当父节点具有XMLNS属性时,子节点必须指定XMLNS属性,但是当子节点的XMLNS属性与父节点命名空间相同时,子节点不显示XMLNS属性,上面问题的根本所在就是我们理解上的错误,我们认为没有为子节点指定命名空间,就不应该出现此属性,恰恰相反,当我们为其指定与父节点相同的命名空间时,此属性才不会出现。


代码如下:

	String text = paramMap.get("text").toString();
		//和父节点命名空间相同,才不会显示,否则会自动加上 xmlns=""
		if(type.equals("addChild")){
			//如果是新增子节点,在add后加上命名空间
			Element newElement = element.addElement(text,"urn:hl7-org:v3");
			reMap.put("id", calculate(elementPath,newElement));
		}else{
			//新增兄弟节点
			Element parentElement = element.getParent();
			List<Object> l = parentElement.content();
            int index = l.indexOf(element);
            //加上命名空间
            Element newElement = parentElement.addElement(text,"urn:hl7-org:v3");
            l.add(index+1, newElement);
            parentElement.setContent(l);
            reMap.put("id", calculate(elementPath.substring(0,elementPath.lastIndexOf("/")),newElement));
		}

代码在hai-mcentre的catalogService的128-144。
Strophe.Builder = function (name, attrs) { // Holds the tree being built. this.nodeTree = this._makeNode(name, attrs); // Points to the current operation node. this.node = this.nodeTree; }; Strophe.Builder.prototype = { /** Function: tree * Return the DOM tree. * * This function returns the current DOM tree as an element object. This * is suitable for passing to functions like Strophe.Connection.send(). * * Returns: * The DOM tree as a element object. */ tree: function () { return this.nodeTree; }, /** Function: toString * Serialize the DOM tree to a String. * * This function returns a string serialization of the current DOM * tree. It is often used internally to pass data to a * Strophe.Request object. * * Returns: * The serialized DOM tree in a String. */ toString: function () { return Strophe.serialize(this.nodeTree); }, /** Function: up * Make the current parent element the new current element. * * This function is often used after c() to traverse back up the tree. * For example, to add two children to the same element * > builder.c('child1', {}).up().c('child2', {}); * * Returns: * The Stophe.Builder object. */ up: function () { this.node = this.node.parentNode; return this; }, /** Function: attrs * Add or modify attributes of the current element. * * The attributes should be passed in object notation. This function * does not move the current element pointer. * * Parameters: * (Object) moreattrs - The attributes to add/modify in object notation. * * Returns: * The Strophe.Builder object. */ attrs: function (moreattrs) { for (var k in moreattrs) this.node.setAttribute(k, moreattrs[k]); return this; }, /** Function: c * Add a child to the current element and make it the new current * element. * * This function moves the current element pointer to the child. If you * need to add another child, it is necessary to use up() to go back * to the parent in the tree. * * Parameters: * (String) name - The name of the child. * (Object) attrs - The attributes of the child in object notation. * * Returns: * The Strophe.Builder object. */ c: function (name, attrs) { var child = this._makeNode(name, attrs); this.node.appendChild(child); this.node = child; return this; }, /** Function: cnode * Add a child to the current element and make it the new current * element. * * This function is the same as c() except that instead of using a * name and an attributes object to create the child it uses an * existing DOM element object. * * Parameters: * (XMLElement) elem - A DOM element. * * Returns: * The Strophe.Builder object. */ cnode: function (elem) { this.node.appendChild(elem); this.node = elem; return this; }, /** Function: t * Add a child text element. * * This *does not* make the child the new current element since there * are no children of text elements. * * Parameters: * (String) text - The text data to append to the current element. * * Returns: * The Strophe.Builder object. */ t: function (text) { var child = Strophe.xmlTextNode(text); this.node.appendChild(child); return this; }, /** PrivateFunction: _makeNode * _Private_ helper function to create a DOM element. * * Parameters: * (String) name - The name of the new element. * (Object) attrs - The attributes for the new element in object * notation. * * Returns: * A new DOM element. */ _makeNode: function (name, attrs) { var node = Strophe.xmlElement(name); for (var k in attrs) node.setAttribute(k, attrs[k]); return node; } }; /** PrivateClass: Strophe.Handler * _Private_ helper class for managing stanza handlers. * * A Strophe.Handler encapsulates a user provided callback function to be * executed when matching stanzas are received by the connection. * Handlers can be either one-off or persistant depending on their * return value. Returning true will cause a Handler to remain active, and * returning false will remove the Handler. * * Users will not use Strophe.Handler objects directly, but instead they * will use Strophe.Connection.addHandler() and * Strophe.Connection.deleteHandler(). */ /** PrivateConstructor: Strophe.Handler * Create and initialize a new Strophe.Handler. * * Parameters: * (Function) handler - A function to be executed when the handler is run. * (String) ns - The namespace to match. * (String) name - The element name to match. * (String) type - The element type to match. * (String) id - The element id attribute to match. * (String) from - The element from attribute to match. * * Returns: * A new Strophe.Handler object. */ Strophe.Handler = function (handler, ns, name, type, id, from) { this.handler = handler; this.ns = ns; this.name = name; this.type = type; this.id = id; this.from = from; // whether the handler is a user handler or a system handler this.user = true; }; Strophe.Handler.prototype = { /** PrivateFunction: isMatch * Tests if a stanza matches the Strophe.Handler. * * Parameters: * (XMLElement) elem - The XML element to test. * * Returns: * true if the stanza matches and false otherwise. */ isMatch: function (elem) { var nsMatch, i; nsMatch = false; if (!this.ns) { nsMatch = true; } else { var self = this; Strophe.forEachChild(elem, null, function (elem) { if (elem.getAttribute("xmlns") == self.ns) nsMatch = true; }); nsMatch = nsMatch || elem.getAttribute("xmlns") == this.ns; } if (nsMatch && (!this.name || Strophe.isTagEqual(elem, this.name)) && (!this.type || elem.getAttribute("type") == this.type) && (!this.id || elem.getAttribute("id") == this.id) && (!this.from || elem.getAttribute("from") == this.from)) { return true; } return false; }, /** PrivateFunction: run * Run the callback on a matching stanza. * * Parameters: * (XMLElement) elem - The DOM element that triggered the * Strophe.Handler. * * Returns: * A boolean indicating if the handler should remain active. */ run: function (elem) { var result = null; try { result = this.handler(elem); } catch (e) { if (e.sourceURL) { Strophe.fatal("error: " + this.handler + " " + e.sourceURL + ":" + e.line + " - " + e.name + ": " + e.message); } else if (e.fileName) { if (typeof(console) != "undefined") { console.trace(); console.error(this.handler, " - error - ", e, e.message); } Strophe.fatal("error: " + this.handler + " " + e.fileName + ":" + e.lineNumber + " - " + e.name + ": " + e.message); } else { Strophe.fatal("error: " + this.handler); } throw e; } return result; }, /** PrivateFunction: toString * Get a String representation of the Strophe.Handler object. * * Returns: * A String. */ toString: function () { return "{Handler: " + this.handler + "(" + this.name + "," + this.id + "," + this.ns + ")}"; } }; /** PrivateClass: Strophe.TimedHandler * _Private_ helper class for managing timed handlers. * * A Strophe.TimedHandler encapsulates a user provided callback that * should be called after a certain period of time or at regular * intervals. The return value of the callback determines whether the * Strophe.TimedHandler will continue to fire. * * Users will not use Strophe.TimedHandler objects directly, but instead * they will use Strophe.Connection.addTimedHandler() and * Strophe.Connection.deleteTimedHandler(). */ /** PrivateConstructor: Strophe.TimedHandler * Create and initialize a new Strophe.TimedHandler object. * * Parameters: * (Integer) period - The number of milliseconds to wait before the * handler is called. * (Function) handler - The callback to run when the handler fires. This * function should take no arguments. * * Returns: * A new Strophe.TimedHandler object. */ Strophe.TimedHandler = function (period, handler) { this.period = period; this.handler = handler; this.lastCalled = new Date().getTime(); this.user = true; }; Strophe.TimedHandler.prototype = { /** PrivateFunction: run * Run the callback for the Strophe.TimedHandler. * * Returns: * true if the Strophe.TimedHandler should be called again, and false * otherwise. */ run: function () { this.lastCalled = new Date().getTime(); return this.handler(); }, /** PrivateFunction: reset * Reset the last called time for the Strophe.TimedHandler. */ reset: function () { this.lastCalled = new Date().getTime(); }, /** PrivateFunction: toString * Get a string representation of the Strophe.TimedHandler object. * * Returns: * The string representation. */ toString: function () { return "{TimedHandler: " + this.handler + "(" + this.period +")}"; } }; /** PrivateClass: Strophe.Request * _Private_ helper class that provides a cross implementation abstraction * for a BOSH related XMLHttpRequest. * * The Strophe.Request class is used internally to encapsulate BOSH request * information. It is not meant to be used from user's code. */ /** PrivateConstructor: Strophe.Request * Create and initialize a new Strophe.Request object. * * Parameters: * (String) data - The data to be sent in the request. * (Function) func - The function that will be called when the * XMLHttpRequest readyState changes. * (Integer) rid - The BOSH rid attribute associated with this request. * (Integer) sends - The number of times this same request has been * sent. */ Strophe.Request = function (data, func, rid, sends) { this.id = ++Strophe._requestId; this.data = data; // save original function in case we need to make a new request // from this one. this.origFunc = func; this.func = func; this.rid = rid; this.date = NaN; this.sends = sends || 0; this.abort = false; this.dead = null; this.age = function () { if (!this.date) return 0; var now = new Date(); return (now - this.date) / 1000; }; this.timeDead = function () { if (!this.dead) return 0; var now = new Date(); return (now - this.dead) / 1000; }; this.xhr = this._newXHR(); }; Strophe.Request.prototype = { /** PrivateFunction: getResponse * Get a response from the underlying XMLHttpRequest. * * This function attempts to get a response from the request and checks * for errors. * * Throws: * "parsererror" - A parser error occured. * * Returns: * The DOM element tree of the response. */ getResponse: function () { var node = null; if (this.xhr.responseXML && this.xhr.responseXML.documentElement) { node = this.xhr.responseXML.documentElement; if (node.tagName == "parsererror") { Strophe.error("invalid response received"); Strophe.error("responseText: " + this.xhr.responseText); Strophe.error("responseXML: " + Strophe.serialize(this.xhr.responseXML)); throw "parsererror"; } } else if (this.xhr.responseText) { Strophe.error("invalid response received"); Strophe.error("responseText: " + this.xhr.responseText); Strophe.error("responseXML: " + Strophe.serialize(this.xhr.responseXML)); } return node; }, /** PrivateFunction: _newXHR * _Private_ helper function to create XMLHttpRequests. * * This function creates XMLHttpRequests across all implementations. * * Returns: * A new XMLHttpRequest. */ _newXHR: function () { var xhr = null; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); if (xhr.overrideMimeType) { xhr.overrideMimeType("text/xml"); } } else if (window.ActiveXObject) { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } xhr.onreadystatechange = this.func.prependArg(this); return xhr; } };
最新发布
08-08
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值