import 'package:test/test.dart';
import 'package:xml/xml.dart';
import 'package:xml/xml_events.dart';
import 'package:xml/xpath.dart';
import 'utils/assertions.dart';
void main() {
const bookshelfXml = '''
Growing a Language
29.99
Learning XML
39.95
132.00
''';
final document = XmlDocument.parse(bookshelfXml);
group('reading and writing', () {
test('parse document', () {
assertDocumentInvariants(document);
});
test('printing document', () {
expect(document.toString(), bookshelfXml);
expect(
document.toXmlString(pretty: true, indent: '\t'),
startsWith(''),
);
});
});
group('traversing and querying', () {
test('extract text', () {
final textual = document.descendants
.whereType()
.map((text) => text.value.trim())
.where((string) => string.isNotEmpty)
.join('\n');
expect(
textual,
'Growing a Language\n'
'29.99\n'
'Learning XML\n'
'39.95\n'
'132.00',
);
expect(
document.innerText,
'\n'
' \n'
' \n'
' Growing a Language\n'
' 29.99\n'
' \n'
' \n'
' Learning XML\n'
' 39.95\n'
' \n'
' 132.00\n'
' ',
);
});
test('find all elements', () {
final titles = document
.findAllElements('title')
.map((element) => element.innerText);
expect(titles, ['Growing a Language', 'Learning XML']);
});
test('nested find elements', () {
final total = document
.findAllElements('book')
.map(
(element) =>
double.parse(element.findElements('price').single.innerText),
)
.reduce((a, b) => a + b);
expect(total, closeTo(69.94, 0.1));
});
test('find all the books in the bookshelf', () {
expect(document.xpath('/bookshelf/book'), hasLength(2));
});
test('find the second book in the bookshelf', () {
expect(document.xpath('/bookshelf/book[2]'), hasLength(1));
});
test('find all the english titles anywhere', () {
expect(document.xpath('//title[@lang="en"]'), hasLength(2));
});
test('find all the books with an english title', () {
expect(document.xpath('//book[title/@lang="en"]'), hasLength(2));
});
test('sum up the prices of all the books', () {
final total = document
.xpath('//book/price/text()')
.map((node) => double.parse(node.value!))
.reduce((a, b) => a + b);
expect(total, closeTo(69.94, 0.1));
});
});
group('building', () {
test('a document', () {
final builder = XmlBuilder();
builder.processing('xml', 'version="1.0"');
builder.element(
'bookshelf',
nest: () {
builder.element(
'book',
nest: () {
builder.element(
'title',
nest: () {
builder.attribute('lang', 'en');
builder.text('Growing a Language');
},
);
builder.element('price', nest: 29.99);
},
);
builder.element(
'book',
nest: () {
builder.element(
'title',
nest: () {
builder.attribute('lang', 'en');
builder.text('Learning XML');
},
);
builder.element('price', nest: 39.95);
},
);
builder.element('price', nest: '132.00');
},
);
final builtDocument = builder.buildDocument();
expect(
document.toXmlString(pretty: true),
builtDocument.toXmlString(pretty: true),
);
});
test('a fragment', () {
void buildBook(
XmlBuilder builder,
String title,
String language,
num price,
) {
builder.element(
'book',
nest: () {
builder.element(
'title',
nest: () {
builder.attribute('lang', language);
builder.text(title);
},
);
builder.element('price', nest: price);
},
);
}
final builder = XmlBuilder();
buildBook(builder, 'The War of the Worlds', 'en', 12.50);
buildBook(builder, 'Voyages extraordinaries', 'fr', 18.20);
final builtDocument = document.copy();
builtDocument.rootElement.children.add(builder.buildFragment());
final titles = builtDocument
.findAllElements('title')
.map((node) => node.innerText);
expect(titles, [
'Growing a Language',
'Learning XML',
'The War of the Worlds',
'Voyages extraordinaries',
]);
});
});
group('event-driven', () {
test('iterable', () {
final result = parseEvents(bookshelfXml)
.whereType()
.map((event) => event.value.trim())
.where((text) => text.isNotEmpty)
.join('\n');
expect(
result,
'Growing a Language\n'
'29.99\n'
'Learning XML\n'
'39.95\n'
'132.00',
);
});
test('stream', () async {
final stream = Stream.fromIterable([bookshelfXml]);
final result = await stream
.toXmlEvents()
.normalizeEvents()
.expand(
(events) => events
.whereType()
.map((event) => event.value.trim())
.where((text) => text.isNotEmpty),
)
.join('\n');
expect(
result,
'Growing a Language\n'
'29.99\n'
'Learning XML\n'
'39.95\n'
'132.00',
);
});
test('stream select subtree', () async {
final stream = Stream.fromIterable([bookshelfXml]);
final result = await stream
.toXmlEvents()
.normalizeEvents()
.selectSubtreeEvents((event) => event.name == 'title')
.toXmlNodes()
.expand((nodes) => nodes)
.map((node) => node.innerText)
.join('\n');
expect(
result,
'Growing a Language\n'
'Learning XML',
);
});
});
}