File Coverage

blib/lib/Document/OOXML/ContentTypes.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1 1     1   45485 use utf8;
  1         2  
  1         6  
2             package Document::OOXML::ContentTypes;
3 1     1   353 use Moose;
  1         386844  
  1         7  
4 1     1   154343 use namespace::autoclean;
  1         77205  
  1         4  
5              
6             # ABSTRACT: Part to content-type mapping for OOXML
7              
8 1     1   192 use XML::LibXML;
  0            
  0            
9              
10              
11             my $CONTENT_TYPES_NS = 'http://schemas.openxmlformats.org/package/2006/content-types';
12              
13             has defaults => (
14             is => 'ro',
15             isa => 'ArrayRef[HashRef]'
16             );
17              
18             has overrides => (
19             is => 'ro',
20             isa => 'ArrayRef[HashRef]'
21             );
22              
23              
24             sub new_from_xml {
25             my $class = shift;
26              
27             my $doc = XML::LibXML->load_xml( string => shift );
28             my $xpc = XML::LibXML::XPathContext->new();
29             $xpc->registerNs('ct' => $CONTENT_TYPES_NS);
30              
31             my @defaults = map {
32             {
33             extension => $xpc->findvalue('@Extension', $_),
34             content_type => $xpc->findvalue('@ContentType', $_),
35             }
36             } $xpc->findnodes('/ct:Types/ct:Default', $doc->documentElement);
37              
38             my @overrides = map {
39             {
40             part_name => $xpc->findvalue('@PartName', $_),
41             content_type => $xpc->findvalue('@ContentType', $_),
42             }
43             } $xpc->findnodes('/ct:Types/ct:Override', $doc->documentElement);
44              
45             return $class->new(
46             defaults => \@defaults,
47             overrides => \@overrides,
48             );
49             }
50              
51              
52             sub get_content_type_for_part {
53             my $self = shift;
54             my $part_name = shift;
55              
56             my ($overridden) = grep { $part_name eq $_->{part_name} } @{ $self->overrides };
57             return $overridden->{content_type} if $overridden;
58              
59             my ($default) = grep { $part_name =~ /\Q.$_->{extension}\E$/ } @{ $self->defaults };
60             return $default->{content_type} if $default;
61              
62             return;
63             }
64              
65             __PACKAGE__->meta->make_immutable();
66              
67             __END__
68              
69             =pod
70              
71             =encoding UTF-8
72              
73             =head1 NAME
74              
75             Document::OOXML::ContentTypes - Part to content-type mapping for OOXML
76              
77             =head1 VERSION
78              
79             version 0.172601
80              
81             =head1 SYNOPSIS
82              
83             my $ct = Document::OOXML::ContentTypes->new_from_xml($xml_data);
84             say "The content type of /word/document.xml is " . $ct->get_content_type_for_part('/word/document.xml');
85              
86             =head1 DESCRIPTION
87              
88             OOXML files contain a file named '[Content_Types].xml' that describes the
89             content-types of all the other files in the package.
90              
91             This class implements a way to look up the content-type for a file name,
92             given the contents of that file.
93              
94             =head1 METHODS
95              
96             =head2 new_from_xml($xml_data)
97              
98             Creates a new L<Document::OOXML::ContentTypes> instance from the contents
99             of the C</[Content-Types].xml> file from an OOXML file.
100              
101             =head2 get_content_type_for_part($part_name)
102              
103             Returns the content-type of the part with the specified name.
104              
105             =head1 SEE ALSO
106              
107             =over
108              
109             =item * L<Document::OOXML>
110              
111             =back
112              
113             =head1 AUTHOR
114              
115             Martijn van de Streek <martijn@vandestreek.net>
116              
117             =head1 COPYRIGHT AND LICENSE
118              
119             This software is copyright (c) 2017 by Martijn van de Streek.
120              
121             This is free software; you can redistribute it and/or modify it under
122             the same terms as the Perl 5 programming language system itself.
123              
124             =cut