the apr_xml_to_text (really the write_text) function should re-escape entities to make valid XML CDATA blocks...For example: --output of example code-- RESULT: (40) <tag>test with an & in the middle</tag> --example code-- #include <apr_pools.h> #include <apr_xml.h> int main(int argc, char **argv) { apr_xml_parser *parser = NULL; apr_pool_t *pool = NULL; apr_xml_doc *pdoc = NULL; int namespace_mapping[100]; char *testxml = "<?xml version=\"1.0\"?>\n<tag>test with an & in the middle</tag>\n"; apr_pool_initialize(); apr_pool_create(&pool, NULL); parser = apr_xml_parser_create(pool); apr_xml_parser_feed(parser, testxml, strlen(testxml)); apr_xml_parser_done(parser, &pdoc); const char *buf = NULL; apr_size_t buflen = 0; apr_xml_to_text(pool, pdoc->root, APR_XML_X2T_FULL, pdoc->namespaces, namespace_mapping, (const char **)&buf, &buflen); printf("RESULT:\n(%ld) %s\n", buflen, buf); apr_pool_destroy(pool); apr_pool_terminate(); }