"Extra content at the end of the document" error using libxml2 to read from file handle created with shm_open

1.4k views Asked by At

I'm trying to write a unit test that checks some xml parsing code. The unit test creates a file descriptor on an in-memory xml doc using shm_open and then passes that to xmlTextReaderForFd(). But I'm getting an "Extra content at the end of the document" error on the subsequent xmlTextReaderRead(). The parsing code works fine on a file descriptor created from an actual file (I've done a byte-for-byte comparison with the shm_open created one and it's the exact same set of bytes.) Why is libxml2 choking on a file descriptor created with shm_open?

Here's my code:

void unitTest() {
  int fd = shm_open("/temporary", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
  char *pText = "<?xml version=\"1.0\"?><foo></foo>";
  write(fd, pText, strlen(pText) + 1);
  lseek(fd, 0, SEEK_SET);

  xmlTextReaderPtr pReader = xmlReaderForFd(
    fd,            // file descriptor
    "/temporary",  // base uri
    NULL,          // encoding
    0);            // options

  int result = xmlTextReaderRead(pReader);
  // result is -1
  // Get this error at console:
  //   /temporary:1: parser error : Extra content at the end of the document
  //   <?xml version="1.0"?><foo></foo>
  //                                   ^
}
2

There are 2 answers

0
Skeets On BEST ANSWER

I figured out the problem. I was writing out the NULL terminator and that's what was causing libxml2 to choke (although I could have sworn I already tried it without the NULL terminator, d'oh!) The fixed code should simply be:

 write(fd, pText, strlen(pText));
0
Pierre On

Also, make sure you are reading the file as binary, not text. 'Text' strips out CR/LF, reduces the size of the file and leaves detritus at the end of the buffer.

Example (VS 2010):

struct _stat32 stat;
char *buf;
FILE *f = fopen("123.XML", "rb");    // right
//f = fopen("123.XML", "rt");    // WRONG!
_fstat(fileno(f), &stat);
buf = (char *)malloc(stat.st_size);
int ret = fread(buf, stat.st_size, 1, f);
assert(ret == 1);
// etc.