xref: /webtrees/app/Report/ReportParserBase.php (revision 299ca8d22e0b70bd405b788311c6116987f1ba96)
1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2018 webtrees development team
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16declare(strict_types=1);
17
18namespace Fisharebest\Webtrees\Report;
19
20use DomainException;
21
22/**
23 * Class ReportParserBase
24 */
25class ReportParserBase
26{
27    /** @var resource The XML parser */
28    protected $xml_parser;
29
30    /** @var string Text contents of tags */
31    protected $text = '';
32
33    /**
34     * Create a parser for a report
35     *
36     * @param string $report The XML filename
37     */
38    public function __construct(string $report)
39    {
40        $this->xml_parser = xml_parser_create();
41
42        xml_parser_set_option($this->xml_parser, XML_OPTION_CASE_FOLDING, false);
43
44        xml_set_element_handler(
45            $this->xml_parser,
46            function ($parser, string $name, array $attrs) {
47                $this->startElement($parser, $name, $attrs);
48            },
49            function ($parser, string $name) {
50                $this->endElement($parser, $name);
51            }
52        );
53
54        xml_set_character_data_handler(
55            $this->xml_parser,
56            function ($parser, $data) {
57                $this->characterData($parser, $data);
58            }
59        );
60
61        $fp = fopen($report, 'r');
62
63        while (($data = fread($fp, 4096))) {
64            if (!xml_parse($this->xml_parser, $data, feof($fp))) {
65                throw new DomainException(sprintf(
66                    'XML error: %s at line %d',
67                    xml_error_string(xml_get_error_code($this->xml_parser)),
68                    xml_get_current_line_number($this->xml_parser)
69                ));
70            }
71        }
72
73        xml_parser_free($this->xml_parser);
74    }
75
76    /**
77     * XML handler for an opening (or self-closing) tag.
78     *
79     * @param resource $parser The resource handler for the xml parser
80     * @param string   $name   The name of the xml element parsed
81     * @param string[] $attrs  An array of key value pairs for the attributes
82     *
83     * @return void
84     */
85    protected function startElement($parser, string $name, array $attrs)
86    {
87        $method = $name . 'StartHandler';
88
89        if (method_exists($this, $method)) {
90            $this->$method($attrs);
91        }
92    }
93
94    /**
95     * XML handler for a closing tag.
96     *
97     * @param resource $parser the resource handler for the xml parser
98     * @param string   $name   the name of the xml element parsed
99     *
100     * @return void
101     */
102    protected function endElement($parser, string $name)
103    {
104        $method = $name . 'EndHandler';
105
106        if (method_exists($this, $method)) {
107            $this->$method();
108        }
109    }
110
111    /**
112     * XML handler for character data.
113     *
114     * @param resource $parser The resource handler for the xml parser
115     * @param string   $data   The name of the xml element parsed
116     *
117     * @return void
118     */
119    protected function characterData($parser, $data)
120    {
121        $this->text .= $data;
122    }
123}
124