The XML::fetchNextRow() method currently returns a SimpleXMLElement when the current selector doesn't render to a string and has children. This seems to be in conflict with core's MigrateExecutable::import() which starts by calling $source->rewind(). This will result in an exception being thrown ("Migration failed with source plugin exception: Serialization of SimpleXMLElement is not allowed"), and the migration is interrupted.
Quickly googling for this problem indicates that SimpleXMLElement can't really be serialized, so returning that as an object is simply not possible. I'm proposing that instead of returning the object, the code should be altered to return the element's XML, which can easily be converted back to the object with simplexml_load_string().
Since might be relevant, in this migration I've got a set of XML files in an import directory (crawled by the hook_install hack), and one of my processors needs to use the XML element, as the specific child being imported depends on a Drupal variable (the XML element contains different translations of a string, and which one gets imported depends on the current site's language).
For more information see this issue https://www.drupal.org/node/2837684
| Comment | File | Size | Author |
|---|---|---|---|
| #2 | migration_failed_with_source_plugin_exception-2912112-1.patch | 770 bytes | focus13 |
Comments
Comment #2
focus13 commentedComment #3
frank ralf commentedMany thanks for the patch! I want to migrate a nested XHTML fragment to the body field which failed. Tested the patch with Acquia desktop (PHP 7.1.11 and Drupal 8.4.4). Works like a charm.
BTW, I didn't get the above mentioned error message so it took me quite a while to find out the missing serialization of the XHTML fragment was the cause of the problem.
Best regards,
Frank
Comment #4
heddnI know we don't have a lot of tests for XML right now. But I'd be afraid this change could cause regressions. Can we add a few tests to show how it worked before and how we want it to work now?
Back to NW for tests.
Comment #5
frank ralf commentedThanks for the quick reply. I don't know much about (automatic) testing. How do I add tests?
Comment #6
heddnhttps://www.drupal.org/docs/8/phpunit
Comment #7
frank ralf commentedThanks. Also found https://www.drupal.org/docs/8/api/migrate-api/migration-tests-in-drupal-8 but I suppose in this case a unit test should suffice?
Comment #8
heddnI would guess that unit would work fine since we are dealing with a pretty small part of the system. No need for more complete integration testing.
Comment #9
frank ralf commentedThanks to your pointers I got PHPUnit up and running. Now I'm thinking about where to put the XML test. AFAIU, it should/could go into modules/migrate_plus/tests/src/Unit/source?
Comment #10
heddnTests tend to mirror the src folder structure. So I'd suggest
tests/src/Unit/Plugin/migrate_plus/data_parser/XmlTest.phpComment #11
frank ralf commentedThanks!
Comment #12
frank ralf commentedHere are some resources regarding testing XML with PHPUnit I found.
Article
Tobias Schlitt, "Practical PHPUnit: Testing XML generation" (2010)
XML-related PHPUnit assertions
Comment #13
badrange commentedThis one bit me today. Luckily I didn't spend too much time scratching my head before I had the idea of googling the error message. Thank you for the patch!
Comment #14
duaelfrIsn't it a duplicate of #2837684: Migration failed with source plugin exception: Serialization of SimpleXMLElement is not allowed?
Comment #15
joegl commentedYea this looks like a 1-for-1 copy of #2837684 and even has a link to it at the bottom of the description.