Skip to content

Inconsistent Behaviour of node.removeChild() #135

Description

@noseworthy

Hello,

I'm seeing some weird behaviour when calling node.removeChild(). If the xml source is "minified" (no pretty formatting) then it removes the first child from the node that I'm calling removeChild() on. If I call removeChild() on the dom instance itself, it replaces the dom instance with an empty string.

If however, the file is pretty printed, and I call dom.removeChild() or node.removeChild() and give it a child node (any child node in the tree) I get the tree returned back with just that node removed.

I'm using xmldom version 0.3.0 in nodejs version 14.12.0 and 10.16.0.

Here's a small mocha test that demonstrates what i'm talking about

const { DOMParser } = require('xmldom');
const { expect } = require('chai');

const MINIFIED_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><parent><child><grandchild attr="value"/></child></parent>`;
const MINIFIED_XML_WITHOUT_GRANDCHILD = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><parent><child/></parent>`;

const PRETTY_PRINTED_XML = `
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<parent>
  <child>
    <grandchild attr="value"/>
  </child>
</parent>
`.trim();
const PRETTY_PRINTED_XML_WITHOUT_GRANDCHILD = `
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<parent>
  <child>
    
  </child>
</parent>`.trim();

describe('remove child test', () => {
  it('removes all content from dom if minified', async () => {
    const dom = new DOMParser().parseFromString(MINIFIED_XML);
    const grandchildren = dom.getElementsByTagName('grandchild');

    expect(grandchildren.length).to.equal(1);
    expect(dom.toString()).to.equal(MINIFIED_XML);

    const grandchild = dom.removeChild(grandchildren[0]);

    expect(grandchild.toString()).to.equal('<grandchild attr="value"/>');
    expect(dom.toString()).to.equal(MINIFIED_XML_WITHOUT_GRANDCHILD);
    expect(dom.toString()).not.to.equal('');
  });

  it('correctly removes grandchild from dom if called on parent element', async () => {
    const dom = new DOMParser().parseFromString(MINIFIED_XML);
    const children = dom.getElementsByTagName('child');
    const grandchildren = dom.getElementsByTagName('grandchild');

    expect(children.length).to.equal(1);
    expect(grandchildren.length).to.equal(1);
    expect(dom.toString()).to.equal(MINIFIED_XML);

    const grandchild = children[0].removeChild(grandchildren[0]);

    expect(grandchild.toString()).to.equal('<grandchild attr="value"/>');
    expect(dom.toString()).to.equal(MINIFIED_XML_WITHOUT_GRANDCHILD);
    expect(dom.toString()).not.to.equal('');
  });

  it('removes just the grandchild node if pretty formatted', async () => {
    const dom = new DOMParser().parseFromString(PRETTY_PRINTED_XML);
    const grandchildren = dom.getElementsByTagName('grandchild');

    expect(grandchildren.length).to.equal(1);
    expect(dom.toString()).to.equal(PRETTY_PRINTED_XML);

    const grandchild = dom.removeChild(grandchildren[0]);

    expect(grandchild.toString()).to.equal('<grandchild attr="value"/>');
    expect(dom.toString()).not.to.equal('');
    expect(dom.toString()).to.equal(PRETTY_PRINTED_XML_WITHOUT_GRANDCHILD);
  });
});

Looking at the docs on MDN (https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild) I'd expect calling removeChild on the dom instance itself to throw a TypeError since I don't think the dom instance is supposed to have removeChild as a function? I'd also maybe expect that calling removeChild() on anything but the child's direct parent to throw a NotFoundError because the node isn't a child of the node.

However, I really like the behaviour that I'm seeing in the pretty printed version of the file. It's real handy to be able to call removeChild on the dom instance and get it to find and remove that child from the tree, wherever it is.

What is the expected behaviour of this method supposed to be?

Thanks!
Mike

Metadata

Metadata

Assignees

Labels

breaking changeSome thing that requires a version bump due to breaking changesbugSomething isn't workinghelp-wantedExternal contributions welcomeneeds investigationInformation is missing and needs to be researched

Type

No type

Fields

No fields configured for issues without a type.

Projects

Status
Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions