xref: /plugin/davcal/vendor/sabre/xml/lib/Element/XmlFragment.php (revision a1a3b6794e0e143a4a8b51d3185ce2d339be61ab)
1*a1a3b679SAndreas Boehler<?php
2*a1a3b679SAndreas Boehler
3*a1a3b679SAndreas Boehlernamespace Sabre\Xml\Element;
4*a1a3b679SAndreas Boehler
5*a1a3b679SAndreas Boehleruse Sabre\Xml\Reader;
6*a1a3b679SAndreas Boehleruse Sabre\Xml\Writer;
7*a1a3b679SAndreas Boehleruse Sabre\Xml\Element;
8*a1a3b679SAndreas Boehler
9*a1a3b679SAndreas Boehler/**
10*a1a3b679SAndreas Boehler * The XmlFragment element allows you to extract a portion of your xml tree,
11*a1a3b679SAndreas Boehler * and get a well-formed xml string.
12*a1a3b679SAndreas Boehler *
13*a1a3b679SAndreas Boehler * This goes a bit beyond `innerXml` and friends, as we'll also match all the
14*a1a3b679SAndreas Boehler * correct namespaces.
15*a1a3b679SAndreas Boehler *
16*a1a3b679SAndreas Boehler * Please note that the XML fragment:
17*a1a3b679SAndreas Boehler *
18*a1a3b679SAndreas Boehler * 1. Will not have an <?xml declaration.
19*a1a3b679SAndreas Boehler * 2. Or a DTD
20*a1a3b679SAndreas Boehler * 3. It will have all the relevant xmlns attributes.
21*a1a3b679SAndreas Boehler * 4. It may not have a root element.
22*a1a3b679SAndreas Boehler */
23*a1a3b679SAndreas Boehlerclass XmlFragment implements Element {
24*a1a3b679SAndreas Boehler
25*a1a3b679SAndreas Boehler    protected $xml;
26*a1a3b679SAndreas Boehler
27*a1a3b679SAndreas Boehler    function __construct($xml) {
28*a1a3b679SAndreas Boehler
29*a1a3b679SAndreas Boehler        $this->xml = $xml;
30*a1a3b679SAndreas Boehler
31*a1a3b679SAndreas Boehler    }
32*a1a3b679SAndreas Boehler
33*a1a3b679SAndreas Boehler    function getXml() {
34*a1a3b679SAndreas Boehler
35*a1a3b679SAndreas Boehler        return $this->xml;
36*a1a3b679SAndreas Boehler
37*a1a3b679SAndreas Boehler    }
38*a1a3b679SAndreas Boehler
39*a1a3b679SAndreas Boehler    /**
40*a1a3b679SAndreas Boehler     * The xmlSerialize metod is called during xml writing.
41*a1a3b679SAndreas Boehler     *
42*a1a3b679SAndreas Boehler     * Use the $writer argument to write its own xml serialization.
43*a1a3b679SAndreas Boehler     *
44*a1a3b679SAndreas Boehler     * An important note: do _not_ create a parent element. Any element
45*a1a3b679SAndreas Boehler     * implementing XmlSerializble should only ever write what's considered
46*a1a3b679SAndreas Boehler     * its 'inner xml'.
47*a1a3b679SAndreas Boehler     *
48*a1a3b679SAndreas Boehler     * The parent of the current element is responsible for writing a
49*a1a3b679SAndreas Boehler     * containing element.
50*a1a3b679SAndreas Boehler     *
51*a1a3b679SAndreas Boehler     * This allows serializers to be re-used for different element names.
52*a1a3b679SAndreas Boehler     *
53*a1a3b679SAndreas Boehler     * If you are opening new elements, you must also close them again.
54*a1a3b679SAndreas Boehler     *
55*a1a3b679SAndreas Boehler     * @param Writer $writer
56*a1a3b679SAndreas Boehler     * @return void
57*a1a3b679SAndreas Boehler     */
58*a1a3b679SAndreas Boehler    function xmlSerialize(Writer $writer) {
59*a1a3b679SAndreas Boehler
60*a1a3b679SAndreas Boehler        $reader = new Reader();
61*a1a3b679SAndreas Boehler
62*a1a3b679SAndreas Boehler        // Wrapping the xml in a container, so root-less values can still be
63*a1a3b679SAndreas Boehler        // parsed.
64*a1a3b679SAndreas Boehler        $xml = <<<XML
65*a1a3b679SAndreas Boehler<?xml version="1.0"?>
66*a1a3b679SAndreas Boehler<xml-fragment xmlns="http://sabre.io/ns">{$this->getXml()}</xml-fragment>
67*a1a3b679SAndreas BoehlerXML;
68*a1a3b679SAndreas Boehler
69*a1a3b679SAndreas Boehler        $reader->xml($xml);
70*a1a3b679SAndreas Boehler
71*a1a3b679SAndreas Boehler        $elementNamespace = null;
72*a1a3b679SAndreas Boehler
73*a1a3b679SAndreas Boehler        while ($reader->read()) {
74*a1a3b679SAndreas Boehler
75*a1a3b679SAndreas Boehler            if ($reader->depth < 1) {
76*a1a3b679SAndreas Boehler                // Skipping the root node.
77*a1a3b679SAndreas Boehler                continue;
78*a1a3b679SAndreas Boehler            }
79*a1a3b679SAndreas Boehler
80*a1a3b679SAndreas Boehler            switch ($reader->nodeType) {
81*a1a3b679SAndreas Boehler
82*a1a3b679SAndreas Boehler                case Reader::ELEMENT :
83*a1a3b679SAndreas Boehler                    $writer->startElement(
84*a1a3b679SAndreas Boehler                        $reader->getClark()
85*a1a3b679SAndreas Boehler                    );
86*a1a3b679SAndreas Boehler                    $empty = $reader->isEmptyElement;
87*a1a3b679SAndreas Boehler                    while ($reader->moveToNextAttribute()) {
88*a1a3b679SAndreas Boehler                        switch ($reader->namespaceURI) {
89*a1a3b679SAndreas Boehler                            case '' :
90*a1a3b679SAndreas Boehler                                $writer->writeAttribute($reader->localName, $reader->value);
91*a1a3b679SAndreas Boehler                                break;
92*a1a3b679SAndreas Boehler                            case 'http://www.w3.org/2000/xmlns/' :
93*a1a3b679SAndreas Boehler                                // Skip namespace declarations
94*a1a3b679SAndreas Boehler                                break;
95*a1a3b679SAndreas Boehler                            default :
96*a1a3b679SAndreas Boehler                                $writer->writeAttribute($reader->getClark(), $reader->value);
97*a1a3b679SAndreas Boehler                                break;
98*a1a3b679SAndreas Boehler                        }
99*a1a3b679SAndreas Boehler                    }
100*a1a3b679SAndreas Boehler                    if ($empty) {
101*a1a3b679SAndreas Boehler                        $writer->endElement();
102*a1a3b679SAndreas Boehler                    }
103*a1a3b679SAndreas Boehler                    break;
104*a1a3b679SAndreas Boehler                case Reader::CDATA :
105*a1a3b679SAndreas Boehler                case Reader::TEXT :
106*a1a3b679SAndreas Boehler                    $writer->text(
107*a1a3b679SAndreas Boehler                        $reader->value
108*a1a3b679SAndreas Boehler                    );
109*a1a3b679SAndreas Boehler                    break;
110*a1a3b679SAndreas Boehler                case Reader::END_ELEMENT :
111*a1a3b679SAndreas Boehler                    $writer->endElement();
112*a1a3b679SAndreas Boehler                    break;
113*a1a3b679SAndreas Boehler
114*a1a3b679SAndreas Boehler            }
115*a1a3b679SAndreas Boehler
116*a1a3b679SAndreas Boehler        }
117*a1a3b679SAndreas Boehler
118*a1a3b679SAndreas Boehler    }
119*a1a3b679SAndreas Boehler
120*a1a3b679SAndreas Boehler    /**
121*a1a3b679SAndreas Boehler     * The deserialize method is called during xml parsing.
122*a1a3b679SAndreas Boehler     *
123*a1a3b679SAndreas Boehler     * This method is called statictly, this is because in theory this method
124*a1a3b679SAndreas Boehler     * may be used as a type of constructor, or factory method.
125*a1a3b679SAndreas Boehler     *
126*a1a3b679SAndreas Boehler     * Often you want to return an instance of the current class, but you are
127*a1a3b679SAndreas Boehler     * free to return other data as well.
128*a1a3b679SAndreas Boehler     *
129*a1a3b679SAndreas Boehler     * You are responsible for advancing the reader to the next element. Not
130*a1a3b679SAndreas Boehler     * doing anything will result in a never-ending loop.
131*a1a3b679SAndreas Boehler     *
132*a1a3b679SAndreas Boehler     * If you just want to skip parsing for this element altogether, you can
133*a1a3b679SAndreas Boehler     * just call $reader->next();
134*a1a3b679SAndreas Boehler     *
135*a1a3b679SAndreas Boehler     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
136*a1a3b679SAndreas Boehler     * the next element.
137*a1a3b679SAndreas Boehler     *
138*a1a3b679SAndreas Boehler     * @param Reader $reader
139*a1a3b679SAndreas Boehler     * @return mixed
140*a1a3b679SAndreas Boehler     */
141*a1a3b679SAndreas Boehler    static function xmlDeserialize(Reader $reader) {
142*a1a3b679SAndreas Boehler
143*a1a3b679SAndreas Boehler        $result = new self($reader->readInnerXml());
144*a1a3b679SAndreas Boehler        $reader->next();
145*a1a3b679SAndreas Boehler        return $result;
146*a1a3b679SAndreas Boehler
147*a1a3b679SAndreas Boehler    }
148*a1a3b679SAndreas Boehler
149*a1a3b679SAndreas Boehler}
150