My first attempt was to use XML::Twig, but the vast number of methods overwhelmed me, and I couldn't find one that simply returns a text representation of all the sub elements (including markup).

Is there an easy way to do it with XML::Twig or another XML module?

I could certainly use regexes to parse the beginning of the file and then paste it verbatim until the second-to-last line in the file, but that seems a bit ugly, so I'd appreciate better suggestions ;-)

Also a more generic way would be to keep the first document, and then to add the other ones at the end, removing their root: ...

I'm not sure how much more "generic" your second solution would be... It might not apply very well, I think, in cases where the quantity of xml data to be concatenated, multiplied by the additional memory consumed for DOM data structure storage in perl, could exceed available RAM.

It's more generic in the sense that it doesn't assume that the root tag of the first document is foo. As you did not mention any constraint on the size of the documents, then I did not assume any.

If there are contraints, for each individual file or for the resulting file, then you should mention it and the solution would be different. Depending on the constraints in terms of speed and potentialsize of the documents, the best solution could be regexp based (that could be made quite robust, provided your XML files do not include DTDs), XML::LibXML based (if individual files are not too big to be loaded in memory), XML::Parser based (rather easy if no DTD is used, a bit more complicated otherwise) or XML::Twig based (slower, but you could deal with arbitrary sized documents, and that would be quite easy to code, although a bit more complex than the examples I gave previously).

But all those potential constraints would be part of the requirements for your code, so you would have to express them if you want a response that really fits your problem.

And no, I am not trying to confuse you to cover up the fact that my answer wasn't that smart ;--)

XML::LibXML::Document has a toString() method that converts the parsed DOM into a string, including all the child nodes. It has an optional format parameter, which, when set to zero "...the document is dumped as it was originally parsed".

Depending on how lazy / strict you're feeling you could either:

just serialize each document into a string and use (anchored) regexes to strip off the document root

use the documentElement() method to get the root of each document, then loop through its childNodes array, and individually toString() each of those

I'd be surprised if there isn't an XML::Twig equivalent to that - I'm just personally much more familiar XML::LibXML - hope that helps.