dlang-community / experimental.xml

A replacement of Phobos std.xml
https://rawgit.com/dlang-community/experimental.xml/gh-pages/index.html
Boost Software License 1.0
11 stars 8 forks source link

Finding immediate child by tag #18

Open wilzbach opened 6 years ago

wilzbach commented 6 years ago

From @talios on July 7, 2017 22:19

Is there an easy(ish) way of finding an immediate child element by tag name?

getElementsByTagName returns a node list of all matching tags, regardless of depth, I see theres a childNodes property not really sure how to iterate it properly ( I tried extracting a loop to a function but can't for the life of me work out what type I should declare a node argument as ( D newbie, it looks like some template specialised type? ).

Anyway, this is the function I have currently:

string mavenVersionFromString(string pomContents)
{
  import std.experimental.xml;
  auto domBuilder = pomContents.parser.cursor.domBuilder;
  domBuilder.setSource(pomContents);
  domBuilder.buildRecursive;
  auto doc = domBuilder.getDocument;
  auto projectNode = doc.getElementsByTagName("project").front;
  auto versionNode = projectNode.getElementsByTagName("version").front;
  auto pomVersion = versionNode.textContent;
  return pomVersion != null ? pomVersion : "unknown";
}

and this is my unittest:

unittest
{
  auto pomContents = `<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>mygroup</groupId>
    <artifactId>myparent</artifactId>
    <version>2.1.19</version>
  </parent>

  <groupId>mygroup</groupId>
  <artifactId>myartifact</artifactId>
  <version>189-beta6-SNAPSHOT</version>
  <packaging>pom</packaging>

</project>`;

  auto pomVersion = pomContents.mavenVersionFromString();
  pomVersion.should.equal("189-beta6-SNAPSHOT").because("the maven artifact version");

}

The getElementsByTagName call for version is finding the /project/parent/version element rather than the desired /project/version ( oh I wish for XPath here ).

What would be the idiomatic D way of handling this?

As an aside, I found it interesting that I had to use getElementsByTagName and NOT getElementsByTagNameNS which I assumed I should do ( which I do in Java, and other XML processing libraries ) since the XML declares a top-level default namespace. Is that due to how the DOMBuilder is built?

Copied from original issue: lodo1995/experimental.xml#43

wilzbach commented 6 years ago

From @talios on July 23, 2017 3:49

Solved with the following:

private auto getChildByTagName(T)(T parent, string name) {
  foreach (child; parent.childNodes) {
    if (child.nodeName == name) {
      return child;
    }
  }
  return null;
}

altho I see the entire library no longer works under the latest DMD release.