instant_xml_parser 1.0.0 instant_xml_parser: ^1.0.0 copied to clipboard
Code generator for instant_xml_parser. Reads specially annotated Dart code an emits an XML parser/deserializer to match.
Generates an XML parser from annotated Dart code #
Need to parse some complex XML?
- Write a set of classes listing the values you want to extract
- Annotate each class with a matching
@tag()
- Annotate fields as needed (e.g. when the field name doesn't match its attribute name)
- Run the generator
- Use your shiny new parser.
This is especially useful when you have a piece of complex XML *cough*OOXML*cough* and want to import the data.
Usage #
Your source #
import 'package:ixp_runtime/annotations.dart';
@tag('ContactInfo')
class ContactInfo {
final String email;
final String phone;
@textElement
final String notes;
ContactInfo(this.email, {this.phone, this.notes = ''});
}
@tag('addressBook')
class AddressBook {
final List<ContactInfo> contacts;
AddressBook(this.contacts);
}
pubspec.yaml #
name: example
description: Annotates data classes for XML deserialization
environment:
sdk: '>=2.10.0 <3.0.0'
dependencies:
ixp_runtime: ^0.9.0
logging: ^0.11.4
xml: ^4.4.0
dev_dependencies:
build_runner: ^1.0.0
build_test: ^0.10.3
instant_xml_parser: ^0.9.0
test: ^1.14.4
Generate your parser from the command line: #
dart pub run build_runner watch --delete-conflicting-outputs
The XML #
<addressBook>
<ContactInfo email="alice@example.com">Birthday: April 1</ContactInfo>
<ContactInfo email="bob@example.com">Birthday: Oct 31</ContactInfo>
</addressBook>');
Parsing #
import 'package:async/async.dart';
import 'package:example/example.dart';
import 'package:xml/xml_events.dart';
StreamQueue<XmlEvent> _eventsFrom(String xml) => StreamQueue(Stream.value(xml)
.toXmlEvents()
.withParentEvents()
.normalizeEvents()
.flatten());
final events = _eventsFrom(
'<addressBook><ContactInfo email="alice@example.com">Birthday: April 1</ContactInfo><ContactInfo email="bob@example.com">Birthday: Oct 31</ContactInfo></addressBook>');
final addressBook = await extractAddressBook(events);
Features #
- Attributes: Non-class fields read as attributes (with implicit or explicit conversion from String). To load a class from an attribute, ensure the class has a static method to instantiate from a String (e.g.
static Foo parse(String s)
) and annotate field with@convert('Foo.parse')
. - Text: Annotate a field with
@textElement
to read its XML text - Classes: Annotate a class definition with
@tag('qualified_name')
to generate a parsing method - Classes: Classes referenced from other classes automatically call that parsing method
- Subclasses: Subclass to implement alternate tags (e.g. if a field can take
<a1>
,<a2>
, or<a3>
, give these a common superclass and use it)
Limitations #
This is not an officially supported Google product.
- Assumes well-formed XML, and will ignore unknown tags/attributes/text in the input stream (but will log such).
- Declaration all has to be in one file (no cross-file references)
- Does nothing with XML comments, processing instructions, etc.
Bugs #
Please file feature requests and bugs at the issue tracker.