File Coverage

blib/lib/Text/Restructured/Writer/LibXML.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Text::Restructured::Writer::LibXML;
2 1     1   34081 use strict;
  1         3  
  1         42  
3 1     1   6 use warnings;
  1         1  
  1         28  
4 1     1   477 use XML::LibXML;
  0            
  0            
5              
6             $Text::Restructured::Writer::LibXML::VERSION='0.01';
7              
8             =head1 NAME
9              
10             Text::Restructured::Writer::LibXML
11              
12             =head1 SYNOPSIS
13              
14             use Text::Restructured;
15             use Text::Restructured::Writer::LibXML;
16              
17             my $parser=Text::Restructured->new($opts,'gino');
18             my $dudom=$parser->Parse($input,$filename);
19             my $xdoc=Text::Restructured::Writer::LibXML->new->ProcessDOM($dudom);
20              
21             =head1 DESCRIPTION
22              
23             This module implements a "Writer" for L, that
24             instead of returning a string, returns a L DOM.
25              
26             The DOM will have non-namespaced elements according to the docutils
27             vocabulary, and namespcaed elements according to the MathML
28             vocabulary.
29              
30             This is probably the fastest way to transform a
31             L structure into a proper XML DOM.
32              
33             =head1 METHODS
34              
35             =head2 C
36              
37             Returns a new object.
38              
39             =cut
40              
41             sub new {
42             my ($class)=@_;
43             return bless {},$class;
44             }
45              
46             =head2 IC<= ProcessDOM(>IC<)>
47              
48             Given an object of type L, processes it
49             recursively and builds an XML DOM into a new document. Returns the
50             document, or dies trying.
51              
52             =cut
53              
54             sub ProcessDOM {
55             my ($self,$dudom)=@_;
56             my $xdoc=XML::LibXML->createDocument();
57             $xdoc->setDocumentElement(_docutils2xml($dudom,$xdoc));
58             return $xdoc;
59             }
60              
61             my $MATHML='http://www.w3.org/1998/Math/MathML';
62              
63             sub _mathml2xml {
64             my ($mnode,$xdoc)=@_;
65              
66             if ($mnode->isText) {
67             return $xdoc->createTextNode($mnode->nodeValue);
68             }
69              
70              
71             my @children=map {_mathml2xml($_,$xdoc)}
72             $mnode->childNodes();
73              
74             my $elem=$xdoc->createElementNS($MATHML,$mnode->nodeName);
75             for my $attname ($mnode->attributeList) {
76             next if $attname eq 'xmlns';
77             $elem->setAttribute($attname,
78             $mnode->attribute($attname))
79             }
80              
81             $elem->appendChild($_) for @children;
82              
83             return $elem;
84             }
85              
86             sub _docutils2xml {
87             my ($dunode,$xdoc)=@_;
88              
89             if ($dunode->{tag} eq '#PCDATA') {
90             return $xdoc->createTextNode($dunode->{text} || '');
91             }
92              
93             if ($dunode->{tag} eq 'mathml') {
94             return _mathml2xml($dunode->{attr}{mathml},$xdoc);
95             }
96              
97             my @children=map {_docutils2xml($_,$xdoc)}
98             @{ $dunode->{content} || [] };
99              
100             my $elem=$xdoc->createElement($dunode->{tag});
101              
102             if (defined $dunode->{attr}) {
103             while (my ($attname,$attval)=each %{$dunode->{attr}}) {
104             if (! defined $attval) {
105             $attval='';
106             }
107             elsif (ref($attval) eq 'ARRAY') {
108             $attval=join ' ',@$attval;
109             }
110             $elem->setAttribute($attname,$attval);
111             }
112             }
113             $elem->appendChild($_) for @children;
114              
115             return $elem;
116             }
117              
118             1;