xml 3.5.0

Dart XML #

Pub Package Build Status Coverage Status GitHub Issues GitHub Forks GitHub Stars GitHub License

Dart XML is a lightweight library for parsing, traversing, querying, transforming and building XML documents.

This library is open source, stable and well tested. Development happens on GitHub. Feel free to report issues or create a pull-request there. General questions are best asked on StackOverflow.

The package is hosted on dart packages. Up-to-date class documentation is created with every release.

Tutorial #

Installation #

Follow the installation instructions on dart packages.

Import the package into your Dart code using:

import 'package:xml/xml.dart' as xml;

Reading and Writing #

To read XML input use the top-level function parse(String input):

var bookshelfXml = '''<?xml version="1.0"?>
    <bookshelf>
      <book>
        <title lang="english">Growing a Language</title>
        <price>29.99</price>
      </book>
      <book>
        <title lang="english">Learning XML</title>
        <price>39.95</price>
      </book>
      <price>132.00</price>
    </bookshelf>''';
var document = xml.parse(bookshelfXml);

The resulting object is an instance of XmlDocument. In case the document cannot be parsed, a XmlParserException is thrown.

To write back the parsed XML document simply call toString(), if you need more control toXmlString(petty: true, indent: '\t'):

print(document.toString());
print(document.toXmlString(pretty: true, indent: '\t'));

Traversing and Querying #

Accessors allow to access nodes in the XML tree:

  • attributes returns a list over the attributes of the current node.
  • children returns a list over the children of the current node.

Both lists are mutable and support all common List methods, such as add(XmlNode), addAll(Iterable<XmlNode>), insert(int, XmlNode), and insertAll(int, Iterable<XmlNode>). Trying to add a null value or an unsupported node type throws an XmlNodeTypeError error. Nodes that are already part of a tree are not automatically moved, you need to first create a copy as otherwise an XmlParentError is thrown. XmlDocumentFragment nodes are automatically expanded and copies of their children are added.

There are various methods to traverse the XML tree along its axes:

  • preceding returns an iterable over nodes preceding the opening tag of the current node in document order.
  • descendants returns an iterable over the descendants of the current node in document order. This includes the attributes of the current node, its children, the grandchildren, and so on.
  • following the nodes following the closing tag of the current node in document order.
  • ancestors returns an iterable over the ancestor nodes of the current node, that is the parent, the grandparent, and so on. Note that this is the only iterable that traverses nodes in reverse document order.

For example, the descendants iterator could be used to extract all textual contents from an XML tree:

var textual = document.descendants
    .where((node) => node is xml.XmlText && !node.text.trim().isEmpty)
    .join('\n');
print(textual);

Additionally, there are helpers to find elements with a specific tag:

  • findElements(String name) finds direct children of the current node with the provided tag name.
  • findAllElements(String name) finds direct and indirect children of the current node with the provided tag name.

For example, to find all the nodes with the <title> tag you could write:

var titles = document.findAllElements('title');

The above code returns a lazy iterator that recursively walks the XML document and yields all the element nodes with the requested tag name. To extract the textual contents call text:

titles
    .map((node) => node.text)
    .forEach(print);

This prints Growing a Language and Learning XML.

Similarly, to compute the total price of all the books one could write the following expression:

var total = document.findAllElements('book')
    .map((node) => double.parse(node.findElements('price').single.text))
    .reduce((a, b) => a + b);
print(total);

Note that this first finds all the books, and then extracts the price to avoid counting the price tag that is included in the bookshelf.

Building #

To build a new XML document use an XmlBuilder. The builder implements a small set of methods to build complete XML trees. To create the above bookshelf example one would write:

var builder = new xml.XmlBuilder();
builder.processing('xml', 'version="1.0"');
builder.element('bookshelf', nest: () {
  builder.element('book', nest: () {
    builder.element('title', nest: () {
      builder.attribute('lang', 'english');
      builder.text('Growing a Language');
    });
    builder.element('price', nest: 29.99);
  });
  builder.element('book', nest: () {
    builder.element('title', nest: () {
      builder.attribute('lang', 'english');
      builder.text('Learning XML');
    });
    builder.element('price', nest: 39.95);
  });
  builder.element('price', nest: 132.00);
});
var bookshelfXml = builder.build();

Note the element method. It is quite sophisticated and supports many different optional named arguments:

  • The most common is the nest: argument which is used to insert contents into the element. In most cases this will be a function that calls more methods on the builder to define attributes, declare namespaces and add child elements. However, the argument can also be a string or an arbitrary Dart object that is converted to a string and added as a text node.
  • While attributes can be defined from within the element, for simplicity there is also an argument attributes: that takes a map to define simple name-value pairs.
  • Furthermore we can provide an URI as the namespace of the element using namespace: and declare new namespace prefixes using namespaces:. For details see the documentation of the method.

The builder pattern allows you to easily extract repeated parts into specific methods. In the example above, one could put the part that writes a book into a separate method as follows:

buildBook(xml.XmlBuilder builder, String title, String language, num price) {
  builder.element('book', nest: () {
    builder.element('title', nest: () {
      builder.attribute('lang', 'english');
      builder.text(title);
    });
    builder.element('price', nest: price);
  });
}

Misc #

Examples #

There are numerous packages depending on this package:

Supports #

  • Standard well-formed XML (and HTML).
  • Reading documents using an event based API (SAX).
  • Decodes and encodes commonly used character entities.
  • Querying, traversing, and mutating API using Dart principles.
  • Building XML trees using a builder API.

Limitations #

  • Doesn't validate namespace declarations.
  • Doesn't validate schema declarations.
  • Doesn't parse and enforce DTD.

History #

This library started as an example of the PetitParser library. To my own surprise various people started to use it to read XML files. In April 2014 I was asked to replace the original dart-xml library from John Evans.

License #

The MIT License, see LICENSE.

Changelog #

3.5.0 #

  • Dart 2.3 compatibility and requirement.
  • Turn various abstract classes into proper mixins.
  • Numerous documentation improvements and code optimizations.
  • Add an event parser example.

3.4.0 #

  • Dart 2.2 compatibility and requirement.
  • Take advantage of PetitParser fast-parse mode:
    • 15-30% faster DOM parsing, and
    • 15-50% faster event parsing.
  • Improve error messages and reporting.

3.3.0 #

  • New event based parsing in xml_events:
    • Lazy event parsing from a XML string into an Iterable of XmlEvent.
    • Async converters between streams of XML, XmlEvent and XmlNode.
  • Clean up package structure by moving internal packages into the src/ subtree.
  • Remove the experimental SAX parser, the event parser allows more flexible streaming XML consumption.

3.2.4 #

  • Remove unnecessary whitespace when printing self-closing tags.
  • Remember if an element is self-closing for stable printing.

3.2.0 #

  • Migrated to PetitParser 2.0

3.1.0 #

  • Drop Dart 1.0 compatibility
  • Cleanup, optimization and improved documentation
  • Add experimental support for SAX parsing

3.0.0 #

  • Mutable DOM
  • Cleaned up documentation
  • Dart 2.0 strong mode compatibility
  • Reformatted using dartfmt

2.6.0 #

  • Fix CDATA encoding
  • Migrate to micro libraries
  • Fixed linter issues

2.5.0 #

  • Generic Method syntax with Dart 1.21

2.4.5 #

  • Do no longer use ArgumentErrors, but instead use proper exceptions.

2.4.4 #

  • Fixed attribute escaping
  • Preserve single and double quotes

2.4.3 #

  • Improved documentation

2.4.2 #

  • Use enum as the node type

2.4.1 #

  • Fixed attribute escaping

2.4.0 #

  • Fixed linter issues
  • Cleanup node hierarchy

2.3.2 #

  • Improved documentation

2.3.1 #

  • Improved test coverage

2.3.0 #

  • Improved comments
  • Optimize namespaces

2.2.2 #

  • Formatted source

2.2.1 #

  • Cleanup pretty printing

2.2.0 #

  • Improved comments

example/README.md

Dart XML Examples #

This package contains examples to illustrate the use of Dart XML. A tutorial and full documentation is contained in the package description and API documentation.

xml_flatten #

This example contains a command-line application that flattens an XML documents from the file-system into a list of events that are printed to the console. For example:

dart example/xml_flatten.dart example/books.xml

xml_pp #

This example contains a command-line application that reads XML documents from the file-system and pretty prints the formatted document to the console.

dart example/xml_pp.dart example/books.xml

xml_grep #

This example contains a command-line application that reads XML documents from the file-system and prints matching tags to the console. For example:

dart example/xml_grep.dart -t title example/books.xml

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  xml: ^3.5.0

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:xml/xml.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
98
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
99
Learn more about scoring.

We analyzed this package on Aug 21, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.4.0
  • pana: 0.12.19

Platforms

Detected platforms: Flutter, web, other

No platform restriction found in primary library package:xml/xml.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.3.0 <3.0.0
collection ^1.14.0 1.14.12
convert ^2.1.0 2.1.1
petitparser ^2.3.0 2.4.0
Transitive dependencies
charcode 1.1.2
meta 1.1.7
typed_data 1.1.6
Dev dependencies
args ^1.5.0
test ^1.6.0