From 216cd30cb526044d09713eed8d977b4f9237c8b1 Mon Sep 17 00:00:00 2001 From: Jirka Svoboda Date: Mon, 22 Apr 2024 11:03:25 +0200 Subject: [PATCH 1/3] fix(ns): imported node namespace is not overidden when specified --- src/builder/XMLBuilderImpl.ts | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/builder/XMLBuilderImpl.ts b/src/builder/XMLBuilderImpl.ts index a135677..de6a338 100644 --- a/src/builder/XMLBuilderImpl.ts +++ b/src/builder/XMLBuilderImpl.ts @@ -377,6 +377,17 @@ export class XMLBuilderImpl implements XMLBuilder { const importedNode = node.node + const updateImportedNodeNs = (clone: Element) => { + // update namespace of imported node only when not specified + if (!clone._namespace) { + const [prefix] = namespace_extractQName( + clone.prefix ? clone.prefix + ':' + clone.localName : clone.localName + ); + const namespace = hostNode.lookupNamespaceURI(prefix) + new XMLBuilderImpl(clone)._updateNamespace(namespace) + } + }; + if (Guard.isDocumentNode(importedNode)) { // import document node const elementNode = importedNode.documentElement @@ -385,18 +396,14 @@ export class XMLBuilderImpl implements XMLBuilder { } const clone = hostDoc.importNode(elementNode, true) as Element hostNode.appendChild(clone) - const [prefix] = namespace_extractQName(clone.prefix ? clone.prefix + ':' + clone.localName : clone.localName) - const namespace = hostNode.lookupNamespaceURI(prefix) - new XMLBuilderImpl(clone)._updateNamespace(namespace) + updateImportedNodeNs(clone) } else if (Guard.isDocumentFragmentNode(importedNode)) { // import child nodes for (const childNode of importedNode.childNodes) { const clone = hostDoc.importNode(childNode, true) hostNode.appendChild(clone) if (Guard.isElementNode(clone)) { - const [prefix] = namespace_extractQName(clone.prefix ? clone.prefix + ':' + clone.localName : clone.localName) - const namespace = hostNode.lookupNamespaceURI(prefix) - new XMLBuilderImpl(clone)._updateNamespace(namespace) + updateImportedNodeNs(clone) } } } else { @@ -404,9 +411,7 @@ export class XMLBuilderImpl implements XMLBuilder { const clone = hostDoc.importNode(importedNode, true) hostNode.appendChild(clone) if (Guard.isElementNode(clone)) { - const [prefix] = namespace_extractQName(clone.prefix ? clone.prefix + ':' + clone.localName : clone.localName) - const namespace = hostNode.lookupNamespaceURI(prefix) - new XMLBuilderImpl(clone)._updateNamespace(namespace) + updateImportedNodeNs(clone) } } From 4d1f29ff28abe90f96e6226a72fdad3dc54c94f1 Mon Sep 17 00:00:00 2001 From: Jirka Svoboda Date: Mon, 22 Apr 2024 13:06:24 +0200 Subject: [PATCH 2/3] fix(ns): keep namespace of imported node childs if defined --- src/builder/XMLBuilderImpl.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/builder/XMLBuilderImpl.ts b/src/builder/XMLBuilderImpl.ts index de6a338..24a1a5f 100644 --- a/src/builder/XMLBuilderImpl.ts +++ b/src/builder/XMLBuilderImpl.ts @@ -384,6 +384,8 @@ export class XMLBuilderImpl implements XMLBuilder { clone.prefix ? clone.prefix + ':' + clone.localName : clone.localName ); const namespace = hostNode.lookupNamespaceURI(prefix) + console.log(prefix, namespace) + new XMLBuilderImpl(clone)._updateNamespace(namespace) } }; @@ -771,7 +773,7 @@ export class XMLBuilderImpl implements XMLBuilder { for (const childNode of ele.childNodes) { const newChildNode = childNode.cloneNode(true) newEle.appendChild(newChildNode) - if (Guard.isElementNode(newChildNode)) { + if (Guard.isElementNode(newChildNode) && !newChildNode._namespace) { const [newChildNodePrefix] = namespace_extractQName(newChildNode.prefix ? newChildNode.prefix + ':' + newChildNode.localName : newChildNode.localName) const newChildNodeNS = newEle.lookupNamespaceURI(newChildNodePrefix) new XMLBuilderImpl(newChildNode)._updateNamespace(newChildNodeNS) From 466c819b03c67b4990748125db61aea1a83ad253 Mon Sep 17 00:00:00 2001 From: Jirka Svoboda Date: Mon, 22 Apr 2024 13:38:10 +0200 Subject: [PATCH 3/3] chore(ns): added test for issue #178, removed console.log --- src/builder/XMLBuilderImpl.ts | 2 -- test/issues/issue-178.test.ts | 57 +++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 test/issues/issue-178.test.ts diff --git a/src/builder/XMLBuilderImpl.ts b/src/builder/XMLBuilderImpl.ts index 24a1a5f..62ea924 100644 --- a/src/builder/XMLBuilderImpl.ts +++ b/src/builder/XMLBuilderImpl.ts @@ -384,8 +384,6 @@ export class XMLBuilderImpl implements XMLBuilder { clone.prefix ? clone.prefix + ':' + clone.localName : clone.localName ); const namespace = hostNode.lookupNamespaceURI(prefix) - console.log(prefix, namespace) - new XMLBuilderImpl(clone)._updateNamespace(namespace) } }; diff --git a/test/issues/issue-178.test.ts b/test/issues/issue-178.test.ts new file mode 100644 index 0000000..4ae0717 --- /dev/null +++ b/test/issues/issue-178.test.ts @@ -0,0 +1,57 @@ +import $$ from '../TestHelpers'; + +describe('Replicate issue', () => { + // https://github.com/oozcitak/xmlbuilder2/issues/90 + describe(`#178 - Namespace is removed when importing fragments.`, () => { + const expectedOutput = $$.t`txt`; + describe(`with defined namespaces on each element`, () => { + test(`using .ele()`, () => { + const doc = $$.create(); + const root = doc.ele('ns1', 'Root'); + const parent = root.ele('ns2', 'Parent'); + const child = parent.ele('ns3', 'Child'); + child.ele('ns4', 'GrandChild').txt('txt'); + + expect(doc.end()).toBe(expectedOutput); + }); + test(`using .import()`, () => { + const doc = $$.create(); + const root = doc.ele('ns1', 'Root'); + const parent = $$.fragment().ele('ns2', 'Parent'); + const child = $$.fragment().ele('ns3', 'Child'); + const grandChild = $$.fragment().ele('ns4', 'GrandChild').txt('txt'); + + child.import(grandChild); + parent.import(child); + root.import(parent); + + expect(doc.end()).toBe(expectedOutput); + }); + }); + describe(`with undefined namespaces on parent element`, () => { + const expectedOutput = $$.t`txt`; + test(`using .ele()`, () => { + const doc = $$.create(); + const root = doc.ele('ns1', 'Root'); + const parent = root.ele('Parent'); + const child = parent.ele('ns3', 'Child'); + child.ele('ns4', 'GrandChild').txt('txt'); + + expect(doc.end()).toBe(expectedOutput); + }); + test(`using .import()`, () => { + const doc = $$.create(); + const root = doc.ele('ns1', 'Root'); + const parent = $$.fragment().ele('Parent'); + const child = $$.fragment().ele('ns3', 'Child'); + const grandChild = $$.fragment().ele('ns4', 'GrandChild').txt('txt'); + + child.import(grandChild); + parent.import(child); + root.import(parent); + + expect(doc.end()).toBe(expectedOutput); + }); + }); + }); +});