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

Comments

focus13 created an issue. See original summary.

focus13’s picture

frank ralf’s picture

Status: Needs review » Reviewed & tested by the community

Many 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

heddn’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

I 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.

frank ralf’s picture

Thanks for the quick reply. I don't know much about (automatic) testing. How do I add tests?

heddn’s picture

frank ralf’s picture

Thanks. 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?

heddn’s picture

I 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.

frank ralf’s picture

Thanks 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?

heddn’s picture

Tests tend to mirror the src folder structure. So I'd suggest tests/src/Unit/Plugin/migrate_plus/data_parser/XmlTest.php

frank ralf’s picture

Thanks!

frank ralf’s picture

Here are some resources regarding testing XML with PHPUnit I found.

Article

Tobias Schlitt, "Practical PHPUnit: Testing XML generation" (2010)

XML-related PHPUnit assertions

badrange’s picture

This 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!

duaelfr’s picture

joegl’s picture

Yea this looks like a 1-for-1 copy of #2837684 and even has a link to it at the bottom of the description.