sabre-io / xml Goto Github PK
View Code? Open in Web Editor NEWsabre/xml is an XML library that you may not hate.
Home Page: http://sabre.io/xml/
License: BSD 3-Clause "New" or "Revised" License
sabre/xml is an XML library that you may not hate.
Home Page: http://sabre.io/xml/
License: BSD 3-Clause "New" or "Revised" License
@staabm, do you have any issues with dropping PHP 5.4 for a 1.3 release?
We produce XML for consumption in glassfish and the XMLs cannot be consumed because of missing encoding declarations.
Hacking Service::write
with $w->startDocument('1.0', 'UTF-8')
did the trick for us.
How should the lib consumer tell sabre-xml which encoding the generated XMLs use?
https://github.com/fruux/sabre-xml/blob/master/lib/Service.php#L186
This is useful for xhtml a
and link
elements, dav href
elements and atom's link
elements and probably many others.
Since I started using the new value-object feature for our contract first webservices I get into the situation where I have to manually define a lot of php value objects, which map 1:1 via the new feature a corresponding XSD.
What do you think about adding a new cli command to create/generate php files from a xsd, in a form that they are 1:1 consumable using the new feature?
I already googled for an hour but wasnt able to find something suitable which isnt part of a huge component or library.
I thought about a very small script, in which you feed in a XSD and creates classes from xsd complexType
s ,interprets min/maxOccurs and some basic types like string
, long
, etc. and adds some docblocks for metainfos which we cannot typehint in php5.5+
at best we would have a lib which does this things already, but I could not find one right now.
This is valid:
<foo xmlns="">bar</foo>
This is not:
<x:foo xmlns:x="">bar</foo>
HHVM has trouble writing attributes that have a namespace-prefix.
A ticket has been opened in the hhvm project.
I think I have some weird, unvalid RSS feed. It has data in xml tags that is encoded with htmlentities. How can I properly decode this?
Example rss feed: http://www.punt.nl/?rss
The fact that parse can return either is annoying.
Hi there
Love the library - great work!
Apologies if this is not the right place to report a possible documentation bug, but I am writing some code that reads XML, and I just upgraded to 1.3 in order to use Sabre\Xml\Deserializers\keyValue
, as it's specified in the Reading XML docs.
However, I got an undefined function
error. A quick look at the library showed me that the namespace is actually Sabre\Xml\Deserializer
, which works fine.
Based on a page search there are about a dozen instances of Deserializers
in the code examples on that page. I assume I am looking at the correct documentation version - apologies if not!
Thanks again,
Darragh
Hello,
I'm trying to use this package to serialize a object to XML.
Declaring it like this
class Invoice implements \Sabre\Xml\XmlSerializable {
public $date;
public $due_date;
function __construct($parameters = array()) {
// auto-populate object..
foreach($parameters as $key => $value) {
$this->$key = $value;
}
}
function xmlSerialize(\Sabre\Xml\Writer $writer) {
$writer->write([ 'date' => $date,
'due_date' => $due_date
]);
}
}
And then calling it up like this
$invoice_data = array(
"date" => $order_object->completed_date,
"due_date" => $order_object->completed_date
);
$invoice = new Invoice($invoice_data);
$writer = new \Sabre\Xml\Writer();
$writer->openMemory();
$writer->writeElement('invoice', $invoice);
$request = $writer->outputMemory();
var_dump($invoice);
var_dump($request);
error_log($request);
Produces a result like this
string '<invoice><date/><due_date/></invoice>'
I've tried to var dump the invoice object and it is well formatted.
Am I doing something wrong?
While we can still break BC, lets rename the elements function to enum. The Sabre\Xml\Element\Elements class has to keep its name though.
Currently there's too much juggling with the result value.
using the namespaceMap
I can define xml-namespaces which get written into the root element of the generated xml.
After adding a xsi
schema namespace into the map via
$namespaces['http://www.w3.org/2001/XMLSchema-instance'] = 'xsi';
how can I make the writer produce a xsi:schemaLocation
location attribute?
I need a xml like
<root-element
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://myns/1 https://host/path/to/my/schema.xsd"
xmlns:x1="http://myns/1"
xmlns:x2="http://myns/2"
...
… this:
<?xml version="1.0" encoding="UTF-8"?>
<vcards xmlns="urn:ietf:params:xml:ns:vcard-4.0">
<vcard>
<ext:my-prop ext:xmlns="http://example.com/extensions/my-vcard">
<parameters>
<pref><integer>1</integer></pref>
</parameters>
<text>value goes here</text>
</ext:my-prop>
</vcard>
</vcards>
because I have Sabre\Xml\LibXMLException: Namespace prefix ext for xmlns on my-prop is not defined on line 4, column 25
. The problem is I don't declare ext
because I don't know it exists.
After using the lib with a few examples I am getting the feeling that the API is very solid and usable but I got stuck in a certain trap several times.
In some situation I need to pass in a clark notation in some others the namespace as a url.
IMO we could improve the developer experience by adding some asserts which fast throw errors in case someone mixed those 2 strings up.
Maybe we could make sure that we consistantly use a var convention which helps the dev to not mix those 2 things ($clark
vs. $namespace
or similar).
We could even handle clark notations in a separate object, but this feels a step too much right now.
(to be honest, I learned clark notation by using the lib... its a term which IMO is not present to everyone therefore would be great to be described somewhere or at least if the docs would link to a article which describes what clark notation actually is)
just a few thoughts to make this lib even better. lets discuss what you guys think.
example:
Service->write
expects arg1 to be given in clark notation. In case you provide just a "name" without a namespace it silently generates a xml which misses a <xml>
document tag
using the following ...
... ValueObject
class ErpOrderResponse {
public $request_id;
public $order_id;
// because this property is missing, things run endless.
// uncommenting the line will make things work again
// public $status;
public $version;
public $success;
}
... XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<order_response xmlns="http://clxERP/order">
<request_id>ErpService:Wed, 23 Dec 2015 13:06:23 +0100</request_id>
<order_id>56652</order_id>
<status>CANCELLED</status>
<version>9</version>
<success>true</success>
</order_response>
... Service
class ErpMarshall extends Sabre\Xml\Service {
const XMLNS_ORDER = "http://clxERP/order";
private $clarkMap = array();
public function __construct() {
// make writer produce non-namespaced elements
$this->namespaceMap[self::XMLNS_ORDER] = null;
$this->mapValueObject('{'. self::XMLNS_ORDER .'}cancel_order_request', 'ErpCancelOrderRequest');
$this->mapValueObject('{'. self::XMLNS_ORDER .'}order_response', 'ErpOrderResponse');
}
public function mapValueObject($elementName, $className) {
parent::mapValueObject($elementName, $className);
$this->clarkMap[$className] = $elementName;
}
public function writeObject($object) {
if (!isset($this->clarkMap[get_class($object)])) throw new Exception('"'. get_class($object) .'" is not a registered value object class');
return $this->write($this->clarkMap[get_class($object)], $object);
}
}
I guess this service class can be simplified further to get a minimal testcase.
things run endless when you do a parse like
$marshall = new ErpMarshall();
var_dump($marshall->parse($xml));
uncommenting the property status
in the ErpOrderResponse
class makes things work as expected.
I agree its a programming mistake, but I feel we need to improve the DX.
As I run the code on the CLI it also never timeouts, which is a different problem ;).
Right now using xml namespaces is a requirement. It would be nice if this were unneeded.
I tried you very basic example with my XML:
$xml = simplexml_load_file('myxml.xml');
$reader = new Sabre\Xml\Reader();
$reader->xml($xml);
print_r($reader->parse());
and got:
Fatal error: Uncaught exception 'Sabre\Xml\LibXMLException' with message 'Extra content at the end of the document on line 42, column 1'
I then tried the same very basic example using your XML and got the same error (I'm using PHP 5.4.21).
Hi
See below my XML file:
<?xml version="1.0"?>
<!--
The contents of this file are subject to the license and copyright
detailed in the LICENSE and NOTICE files at the root of the source
tree and available online at
http://www.dspace.org/license/
-->
<catalogue xml:lang="en" xmlns:i18n="http://apache.org/cocoon/i18n/2.1">
<!--
The format used by all keys is as follows
xmlui.<Aspect>.<Java Class>.<name>
There are a few exceptions to this naming format,
1) Some general keys are in the xmlui.general namespace
because they are used very frequently.
2) Some general keys which are specific to a particular aspect
may be found at xmlui.<Aspect> without specifying a
particular java class.
-->
<!-- General keys -->
<message key="xmlui.general.dspace_home">DSpace Home</message>
<message key="xmlui.general.search">Search</message>
<message key="xmlui.general.go">Go</message>
<message key="xmlui.general.go_home">Go to DSpace home</message>
<message key="xmlui.general.save">Save</message>
<message key="xmlui.general.cancel">Cancel</message>
<message key="xmlui.general.return">Return</message>
<message key="xmlui.general.update">Update</message>
<message key="xmlui.general.delete">Delete</message>
</catalogue>
I have a problem when I try read the XML:
$reader = new \Sabre\Xml\Reader();
$reader->elementMap = [
'{http://apache.org/cocoon/i18n/2.1}catalogue' => 'Sabre\Xml\Element\Base',
];
$reader->xml($pathMyXML);
print_r($reader->parse());
LibXMLException in Reader.php line 75:
Document is empty
on line 1, column 1
in Reader.php line 75
at Reader->parse() in Reader.php line 30
at Reader->__construct() in controllers.php line 62
at {closure}(object(Request))
at call_user_func_array(object(Closure), array(object(Request))) in HttpKernel.php line 147
at HttpKernel->handleRaw(object(Request), '1') in HttpKernel.php line 68
at HttpKernel->handle(object(Request), '1', true) in Application.php line 540
at Application->handle(object(Request)) in Application.php line 521
at Application->run() in index_dev.php line 22
Hi,
I have an XML input with encoding problems.
I use the default KeyValue element ;
Because of the encoding problem, the function "keyValue" is strucked in the loop ; the reader object never reach the node "Reader::END_ELEMENT".
I've tried both :
do {
if ($reader->nodeType === Reader::ELEMENT) {
if ($namespace !== null && $reader->namespaceURI === $namespace) {
$values[$reader->localName] = $reader->parseCurrentElement()['value'];
} else {
$clark = $reader->getClark();
$values[$clark] = $reader->parseCurrentElement()['value'];
if (false === $values[$clark]) {
$reader->next();
}
}
} else {
$reader->read();
}
} while ($reader->nodeType !== Reader::END_ELEMENT);
do {
if ($reader->nodeType === Reader::ELEMENT) {
if ($namespace !== null && $reader->namespaceURI === $namespace) {
$values[$reader->localName] = $reader->parseCurrentElement()['value'];
} else {
$clark = $reader->getClark();
$values[$clark] = $reader->parseCurrentElement()['value'];
if (false === $values[$clark]) {
$reader->read();
}
}
} else {
$reader->read();
}
} while ($reader->nodeType !== Reader::END_ELEMENT);
It doesn't work, reader styled stucked on the same element =/
Any idea/way to skip element and move further ?
Thanks,
Regards
When the library attempts to parse an XML file which is invalid, the script hangs and maxes out the CPU. It would be better if an exception was thrown when invalid XML is detected. The following XML can recreate this issue:
<test>
<hello>
</hello>
</sffsdf>
hope its ok to open a support request here.
In my use-case I have a lot of xml which maps 1:1 to PlainOldPHPObjects like
<order_response xmlns="http://mydomain.de/myobject">
<request_id>4711</request_id>
<order_id>54752</order_id>
<status>INITIALIZED</status>
<success>true</success>
</order_response>
and classes like
class OrderResponse
{
public $request_id;
public $order_id;
public $status;
public $success;
}
no attributes involved. max complexitiy is having some "subobjects" (complex-properties).
is it really required to implement in all my POPO Objects per class xmlDeserialize
and xmlSerialize
logic? Or is there a simpler way to achieve that?
Any guidance is welcome ;)
When the XML is not in a namespace, all the element names are set to null.
This can be remedied by replacing https://github.com/fruux/sabre-xml/blob/master/lib/Sabre/XML/Reader.php#L56 with:
return $this->localName;
Not sure if this causes any issues elsewhere. But I know the testGetClarkNoNS will need to be updated to pass.
It's pointless to release anything if nobody can use it;)
When I use Reader and the KeyValue::xmlDeserialize with invalid XML, the KeyValue class seems to get hung up until it hits max_execution_time and throws a FatalErrorException.
I can't seem to figure out how to catch this FatalErrorException. I'd like a way to deal with invalid XML, because it happens from time-to-time and it currently locks up the application for a while, for the user.
Do you have any recommendations?
Today I ran into a issue because I forgot to return a value from my deserializer callable.
Is there a valid use-case to return null
from a deserilizer or could we improve DX by throwing a Exception
with a proper message when a deserilizer doesnt return anything aka returns `null´?
In case someone defines a deserilizer method, shouldnt it be obligatory to return a proper deserialized value?
Running into this all the time, it's worth making a standard function for it. I suspect that this is what I'll use 90% of the time instead of parseInnerTree.
PHPUnit already has assetXmlStringEqualsXmlString, but it would be nice if we could add a similar function that treats different xml namespaces as identical, and can also ignore additional elements.
Bit of an unfortunate change, and it also sadly does not match Sabre\DAV and Sabre\HTTP.
Using camel-case for abbreviations is more sane though, and matches what the rest of the PHP world is doing. Since Sabre\XML is unreleased, we have a unique chance to fix this before this is set in stone as well.
The following file:
<?php
ini_set('display_errors', '1');
require('vendor/autoload.php');
$contents = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<definitions>
<collaboration>
<participant id="sid-A33D08EB-A2DE-448F-86FE-A2B62E98818" name="Company" processRef="sid-A0A6A196-3C9A-4C69-88F6-7ED7DDFDD264">
<extensionElements>
<signavio:signavioMetaData metaKey="bgcolor" />
""Administrative w">
<extensionElements>
<signavio:signavioMetaData metaKey="bgcolor" metaValue=""/>
</extensionElements>
</lan
XML;
$xmlReader = new \Sabre\Xml\Reader();
$xmlReader->xml($contents);
$xmlReader->parse();
when run does not stop executing. The while loop in the parseInnerTree
does not stop, since $this->nodeType
always stays at 14 (Significant whitespace) and never reaches the end element. When something is added to the xml the issue still occurs, but when something is removed from the xml a proper error message is thrown indicating that "Namespace prefix signavio on signavioMetaData is not defined".
It seems to be a bug in PHP itself, however, I have not been able to replicate it without this library. And since I do not known enough about this library to be sure that it is a bug in PHP.
Note that this bug makes it possible to DDOS the server, since the script gets stuck at 100% CPU.
My specifications:
Cannot use it with PHP 5.3 because you use the PHP 5.4 array Syntax [].
$elementMap
https://github.com/evert/sabre-xml/blob/master/lib/Sabre/XML/Reader.php
In sabre/dav we use a reader for all xml (soon)
We have a central 'elementMap'. All elements are registered centrally. This way we can just call 'parse' from wherever and things will 'just work'.
One issue is that in a lot of places when we do parse, we actually expect to receive a very specific element. It would be nice if we can indicate that right when we start parsing, so sabre/xml can throw an exception for us if we got an unexpected element.
One sabre/dav use-case that I hope to fix with sabre/xml after all these years, is the ability to extract a fragment of xml from a larger document.
Take for instance:
<?xml version="1.0"?>
<d:prop xmlns:d="DAV:">
<d:owner>
<d:href>/principals/users/evert/</d:href>
</d:owner>
</d:prop>
In this example, the owner property is a so-called complex property. Anything that embeds xml elements would be considered 'complex' in this case.
If a client sets that property on a node, we may need to store the complete value. For string-only values this is easy, but for complex properties it means we need to store a fragment of the xml document.
With XMLReader's 'readInnerXml' this is finally easy, as it can give us a string such as this:
<d:owner xmlns:d="DAV:">
<d:href>/principals/users/evert/</d:href>
</d:owner>
XMLWriter doesn't really have an equivalent yet, so we'll need to write a serializer for this that fires up a Reader and pipes it to a writer.
Is there a way to Serialize multiple children?
By way of an example, if I wanted to create the following XML document:
<entity>
<childentity attr1=“attr1” attr2=“attr2” />
<childentity attr1=“attr1” attr2=“attr2” />
</entity>
In theory, I should be able to do the following?
<?php
class ChildEntity implements \Sabre\Xml\XmlSerializable
{
function xmlSerialize(\Sabre\Xml\Writer $writer)
{
$writer->write([
[
'name' => 'childentity',
'attributes' => ['attr1' => 'attr1', 'attr2' => 'attr2'],
'value' => ''
]
]);
}
}
$writer = new \Sabre\Xml\Writer();
$writer->openMemory();
$writer->startElement('entity');
$writer->write([
new ChildEntity(),
new ChildEntity()
]);
$write->endElement();
echo $writer->outputMemory();
But this fails with the error:
When passing an array to ->write with numeric indices, every item must be an array containing the "name" and "value" key
Support for callbacks in the elementMap. Should make it a bit easier to create strategies for reading xml.
Is the silence operator still needed?
(also the one mentioned in #87 )
https://github.com/fruux/sabre-xml/blob/master/lib/Reader.php#L65
https://github.com/fruux/sabre-xml/blob/master/lib/Reader.php#L145
It seems the issue/bug has been fixed
https://bugs.php.net/bug.php?id=64230
Testing your example code from that bug report
does not throw errors here (php 5.6.14)
Not sure if this is the right place to ask questions like this, but here goes...
The reading documentation gives examples of a Book
object being created using elementMap
. With the example, the book
element is just a wrapper and contains nothing but child elements.
<book>
<title>Snow Crash</title>
<author>Neil Stephenson</author>
</book>
The elementMap
handler has access to all those child elements, as its context is book
.
I have xml that looks more like this:
<book isbn="123456781234" publisher="Acme Publishing">
<details title="Snow Crash" author="Neil Stephenson" />
</book>
So now when handling the book
element, I need not only the child elements (and mine goes down a couple of more levels) but also attributes of the book
element. How would I access those attributes in a handler like this:
$reader->elementMap = [
'{whatever}book' => function ($writer) {
// ???
},
];
I'm not asking for a complete solution, but just how to access the current book
element attributes at ???
. I could do it one wrapper element further up, but then have such a complex data structure to handle, it makes elementMap
redundant.
Just writing that, the thought has come to me that this book
level could be used to simplify the detail
(and friends) elements into a flatter structure, then when putting together books
there is a much simpler data structure to parse. Would that be a good way to go about this?
Hi SabreDav,
Actually Im using this for map xml to entity and reverse, but I dont get to put it to work..
This is my code:
use Sabre\XML\Reader;
$xmlData = "
<Test>
<fieldName>value</fieldName>
</Test>
";
$reader = new Reader();
$reader->elementMap = [
'{http://www.w3.org/2005/Atom}link' => 'Test'
];
$reader->xml($xmlData);
$output = $reader->parse();
//Print an array without names of keys,just values
print_r($output);
In other hand in my class, using the example:
use Sabre\XML;
class Test implements XML\Element{
.......
static public function deserializeXml(XML\Reader $reader)
{
$attributes = $reader->parseAttributes();
$link = new self();
foreach($attributes as $name=>$value) {
if (property_exists($link,$name)) {
$link->$name = $value;
}
}
$reader->next();
return $link;
} // Just like in the example
}
Then I try to get the object:
$lead = new Test();
$link = $lead->deserializeXml($reader);
print_r($link->fieldName);
But its null, is there something wrong?
Thanks a lot for help...!
Lets face it, people hate clark notation.
We should add the ability for people to register and use prefixes during reading and writing. The prefixes used during reading are independent of the actual declared prefixes in the xml document, so it basically behaves similarly to registerXPathNamespace
in simplexml.
Example
$writer->namespaceMap = [
'd' => 'DAV:',
];
$writer->write('d:foo', 'bar');
/// Instead of:
$writer->write('{DAV:}foo', 'bar');
The change in the preceding example may seem minimal, but most namespace declarations are not 4 characters, they are massive urls.
It's a bit of a different story with reading though, as for writing, we can easily support both syntaxes unambiguously at the same time:
$writer->write('d:foo', 'bar');
$writer->write('{DAV:}foo', 'bar');
During reading though, a choice needs to be made. Or can we make it optional?
Right now we need to do something like this for a KeyValue:
$reader->elementMap['someelementname'] = 'Sabre\\Xml\\Element\\KeyValue';
With PHP 5.5 we can at least do this:
$reader->elementMap['someelementname'] = KeyValue::name;
But it still requires an import. I wonder if there's a way we could just do this:
$reader->elementMap['someelementname'] = KEYVALUE;
But I don't even know if we can import constants.
This is my XML fragment:
<despatchNote ID="383265">
<detail ID="1" isbn="9781909633773" Qty="1" Status="OK" UMC="1.86"></detail>
<detail ID="2" isbn="9781909633896" Qty="1" Status="--- Book not in Catalogue --" UMC="0"></detail>
</despatchNote>
I want to turn each detail
tag into a DespatchNoteLine
object. The following goes into an infinite loop, creating DespatchNoteLine objects until the request runs out of memory.
$reader->elementMap = [
'{}detail' => function ($reader) {
$attributes = $reader->parseAttributes();
return new DespatchNoteLine($attributes);
},
...
I get around this by parsing the inner elements (even though there are no inner elements):
$reader->elementMap = [
'{}detail' => function ($reader) {
$attributes = $reader->parseAttributes();
\Sabre\Xml\Element\Base::xmlDeserialize($reader); // <<<=== The fix.
return new DespatchNoteLine($attributes);
},
...
Is this expected behaviour? Should it be necessary to always explicitly parse or "consume" inner elements? My impression is that not parsing what's inside the detail
elements would simply discard what's in there. But perhaps I'm looking at it wrong - the parser will parse everything and the mapping is a layer that sits on top of that.
Any thoughts?
To make it easier to get fully qualified uris
Hello,
I have problems with the XML library when datas in event are important.
Have you ever had its warning ?
PHP Warning·XMLWriter::text(): Memory allocation failed : buffer error: text too long
PHP Warning·XMLWriter::text(): Memory allocation failed : growing buffer
It would be nice if we can allow an Element in a document to start a new 'context' during reading or writing. This has the following advantages:
elementMap
for specific parts of a document. In a lot of (arguably badly designed) xml documents, the meaning of an element may vary depending on which element it's in.xml:baseURI
).So it would be awesome if an Element
can push
a new context. After the 'inner' part of the element has been either serialized or deserialized, the context can be popped
again, which will make the reader or writer go back to the previous state.
Example:
function deserializeXml(Reader $reader) {
$reader->pushContext();
$reader->elementMap['{DAV:}prop'] = 'SomeClass';
$result = new self(
$reader->parseInnerTree()
);
$reader->popContext();
return $result
}
The last example is a deserialize function that tells the reader to use a different reader class for {DAV:}prop
elements that are nested within. After reading all inner elements (with parseInnerTree()
), the old state is restored.
Hi, thanks for this library it helped me a lot :)
There is an error in the XEP-0054 specification. The following XML isn't valid, but is used by the XMPP specification.
<body rid='897878733' xmlns='http://jabber.org/protocol/httpbind' sid='7862'><iq from='[email protected]' to='33.33' type='get' xmlns='jabber:client' id='1:sendIQ'><query xmlns='http://jabber.org/protocol/disco#info' node='undefined#undefined'/></iq><iq type='get' xmlns='jabber:client' id='2:sendIQ'><query xmlns='jabber:iq:roster'/></iq><iq type='get' to='[email protected]' xmlns='jabber:client' id='3:sendIQ'><vCard xmlns='vcard-temp'/></iq></body>
The real problem is the <iq type='get' to='[email protected]' xmlns='jabber:client' id='3:sendIQ'><vCard xmlns='vcard-temp'/></iq
element. Causing the following error:
exception 'Sabre\Xml\LibXMLException' with message 'xmlns: URI vcard-temp is not absolute
on line 1, column 141' in /var/www/owncloud/apps/ojsxc/vendor/sabre/xml/lib/Reader.php:158
Is there a way to ignore this error and just parse the valid xml? Thanks!
Running your example causing PHP throwing memory exceeded error
Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 76 bytes) in .../vendor/sabre/xml/lib/Sabre/XML/Reader.php on line 219
Sample code
include __DIR__ . '/vendor/autoload.php';
$reader = new XML\Reader();
$reader->elementMap = [
'{http://www.w3.org/2005/Atom}link' => 'AtomLink'
];
$reader->open('vendor/sabre/xml/samples/atom.xml');
$output = $reader->parse();
var_dump($output);
AtomLink class
use Sabre\XML;
class AtomLink implements XML\Element {
public $href;
public $rel;
public $type;
/**
* The serialize method is called during xml writing.
*
* It should use the $writer argument to encode this object into XML.
*
* Important note: it is not needed to create the parent element. The
* parent element is already created, and we only have to worry about
* attributes, child elements and text (if any).
*
* @param XML\Writer $reader
* @return void
*/
public function serializeXml(XML\Writer $writer) {
$writer->writeAttribute('href', $this->href);
$writer->writeAttribute('rel', $this->rel);
$writer->writeAttribute('type', $this->type);
}
/**
* The deserialize method is called during xml parsing.
*
* This method is called statictly, this is because in theory this method
* may be used as a type of constructor, or factory method.
*
* Often you want to return an instance of the current class, but you are
* free to return other data as well.
*
* @param XML\Reader $reader
* @return mixed
*/
static public function deserializeXml(XML\Reader $reader) {
$attributes = $reader->parseAttributes();
$link = new self();
foreach($attributes as $name=>$value) {
if (property_exists($link,$name)) {
$link->$name = $value;
}
}
return $link;
}
}
I think it has something to do with the Reader::elementMap
method, as soon as I comment it out, it works fine.
PHP Version 5.4.4
@staabm , are you on irc?
I still have a few unittests to write, but other than that.. do you see any reason not to release? Would be nice to get it out before 2016.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.