-
-
Notifications
You must be signed in to change notification settings - Fork 585
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds XML namespaces support #58
Conversation
Could use this. 👍 |
if (!isset($data->$name)) { | ||
return; | ||
if ($metadata->xmlPrefix !== '') { | ||
$nodes = $data->xpath('./'.$metadata->xmlPrefix.':'.$name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this could be improved. If the XML namespaces are registered when the root simplexml element is created, we could unserialize the xml regadless the prefix used at the payload data. But the prepare function at https://github.com/ajgarlag/serializer/blob/xml-namespaces/src/JMS/Serializer/XmlDeserializationVisitor.php#L57 has no access to the ClassMetadata in order to call SimpleXMLElement::registerXPathNamespace with the namespaces declared at the XmlNamespace annotations
Any idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will be tricky to add the namespaces in the prepare
method. However, I think it should also work if we add them when we start visiting an object, i.e. startVisitingObject
, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it should work, but I don't see how to access to the SimpleXMLElement inside XmlDeserializationVisitor::startVisitingObject
in order to register the xpath namespaces
In general this looks quite good. I think we need some additional tests to ensure that the aliases which are used on deserialization do not have to match the aliases that were used on serialization as long as the namespace they refer to is the same. Also, if you switch the |
The problem I see with Anyway, if you prefer to have |
I'd prefer the I've also thought a bit more about the namespace resolution process. So far, we have mostly viewed a single class and then it makes sense to use only the prefix. However, let's assume you have a base class and annotate some namespace. Then, in the sub-class you again annotate some namespace, but re-define prefixes of the parent class with a different namespace. /** @XmlNamespace("http://foo", prefix = "foo") */
abstract class BaseClass {
/** @XmlAttribute(nsprefix = "foo") */ // namespace: http://foo
private $bar;
}
/**
* @XmlNamespace("http://foo", prefix = "old_foo")
* @XmlNamespace("http://better.foo", prefix = "foo")
*/
class SubClass extends BaseClass {
/** @XmlAttribute(nsprefix = "foo") */ // namespace: http://better.foo
private $moo;
} In order to support this, I think we need to resolve the nsprefix to the full URI when we store the metadata (instead of storing the prefix), and then again look up the prefix depending on the actual class during serialization. If you agree, maybe you can also add a test case for the above scenario? |
Another test-case that we need to define: /** @XmlNamespace("http://foo") */
abstract class BaseClass {
/** @XmlAttribute */
private $bar;
}
/** @XmlNamespace("http://better.foo") */
class SubClass extends BaseClass {
/** @XmlAttribute */
private $moo;
} In such a case, some automatic resolution/generation of prefixes seems to be ideal to me. After all, the consuming code should never rely on the namespace prefix, but only ever of the full namespace URI; so the exact value of the prefix should be irrelevant except for cosmetic purposes/humans. |
@schmittjoh Finally here is the refactorization of Example: /**
* @Type("string")
* @Groups({"comments","post"})
* @XmlElement(namespace="http://purl.org/dc/elements/1.1/");
*/
private $title;
/**
* @Type("string")
* @XmlAttribute(namespace="http://schemas.google.com/g/2005")
* @Groups({"post"})
*/
private $etag; Please, review it if you can. |
Looks really good! Thanks for your work on this. It's quite a big feature, and I think we still need a few more test cases; specifically for the following scenarios:
|
Regarding the second scenario: are the child classes supposed to inherit the parent metadata? If I try something like this: /** @XmlNamespace("http://foo", prefix = "foo") */
abstract class BaseClass {
/** @XmlAttribute(namespace = "http://foo") */
public $bar;
}
/**
* @XmlNamespace("http://foo", prefix = "old_foo")
* @XmlNamespace("http://better.foo", prefix = "foo")
*/
class SubClass extends BaseClass {
/** @XmlAttribute(namespace = "http://better.foo") */
public $moo;
} The ClassMetadata for Am I doing something wrong? |
Forget my last comment about the second scenario. Finally, I've been able to test the |
Please review the new tests, specifically I don't know if that is the expected behaviour with classes and subclasses |
ping @schmittjoh |
need this functionality 👍 |
How would this work with something like the XmlList attribute? |
Works nice, +1 to merge into master |
@schmittjoh can you merge this feature? We really need this and it's been 6 months... |
$element = $this->document->createElement($this->namingStrategy->translateName($metadata)); | ||
$elementName = $this->namingStrategy->translateName($metadata); | ||
if ('' !== $namespace = (string) $metadata->xmlNamespace) { | ||
if (!$prefix = $this->document->lookupPrefix($namespace)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ajgarlag it should be always checked in relation of current node (the lookup algorithm checks from the current node up to the root), otherwise object's properties inside objects will have a auto-generated prefix, even if it was been declared:
Consider the following mapping:
<?xml version="1.0" encoding="UTF-8"?>
<serializer>
<class name="Acme\Parent" xml-root-name="package">
<xml-namespace uri="http://acme-parent.com"/>
<property name="child" type="Acme\Child" />
</class>
</serializer>
<?xml version="1.0" encoding="UTF-8"?>
<serializer>
<class name="Acme\Child" xml-root-name="child">
<xml-namespace uri="http://acme-child.com" prefix="dc" />
<property name="data" type="string" xml-namespace="http://acme-child.com" />
</class>
</serializer>
This is the current result:
<?xml version="1.0" encoding="UTF-8"?>
<parent xmlns="http://acme-parent.com">
<child xmlns:ns-04de78c1="http://acme-child.com">
<ns-04de78c1:data xmlns:ns-04de78c1="http://acme-child.com"><![CDATA[lorem-ipsum]]></ns-04de78c1:data>
</child>
</parent>
This is the result doing the lookup in the current node and moving the call to addNamespaceAttributes
in the method startVisitingObject
out of the if statement:
<?xml version="1.0" encoding="UTF-8"?>
<parent xmlns="http://acme-parent.com">
<child xmlns:dc="http://acme-child.com">
<dc:data><![CDATA[lorem-ipsum]]></dc:data>
</child>
</parent>
Could anyone say, what is missing to reach consensus on this topic? I recently came across an XML, that uses namespace and I need to deserialize it. Will help to resolve this issue in anyway I can if it is needed. Anyone? |
Any updates on this issue? |
I am very busy these days, but I'll try to find time to work on this PR soon. |
Hi maybe you can wait some more days. I am ready with changing the deserialization visitor to the same system the serialization visitor works: on the DOMDocument Objekt. All Tests (Even more than before) are Green for Deserialization of XML. Only need to fix my history before i can make a PR. Maybe i will do it this night. With this you will have a better basement for the namespace issue. |
Any movement with that at all? Any current workaround for namespaces with what is already implemented? |
As far as I know there were some outstanding things, that @ajgarlag is working on, but maybe you can lend him a hand. |
@marcospassos Yesterday, @jeserkin contacted me to help with this PR and he is already working on it. Maybe you can contact him to avoid duplicate work. I won't have any time to work on this PR until february, so I'll appreciate your help. |
@ajgarlag thanks for the alert. @jeserkin, have you read my considerations above? BTW, these are the required changes to fix the mentioned bugs: |
@marcospassos read it recently. If you fixed needed bugs, then be sure to send PR to @ajgarlag or straight here as you want. |
I'm not able to send a PR to @ajgard once I've rebased my fork. You can check the changes here (just two lines). |
@marcospassos yes yes. I've seen them. I will send it then. UPD: Is everyone getting nasty UPD:* Hapens during |
… and static properties
Problem exposed by @marcospassos in #58 (comment)
I've found some time to rebase my old PR. It now includes a test to expose the problem detected by @marcospassos and his fix. It's located in a new branch in my repo called xml-namespaces-rebased. Could you do a quick test of it? |
thanks, @ajgarlag! Nice work! |
Seems, that all tests are correct at |
Could you send a new PR for that, or update this PR? |
@schmittjoh I've updated the PR. Could you review it? |
Great work, thanks! One thing which was not included in this PR is some documentation. Maybe someone can write a few lines about the new annotations/config options. |
@schmittjoh, is this website based on |
Yes. |
Would this merge, and thereby the addition of important functionality for XML serialization, justify a new tagged version (for instance 0.15.0)? This way referencing to a stable version becomes easy with Composer ;) |
@schmittjoh once #219 is merged, can we have a new tagged version? |
I've tried to implement the XML namespaces support for serialization and deserialization.
Please, review it if you can and tell me what you think about.