#783 XDoc to string

tactics Wed 14 Oct 2009

I am having trouble converting an XDoc object to a Str. It seems like the most basic thing you can do with it, but the API doesn't make it obvious how to do it.

My first thought was to use XDoc.toStr. This only prints out the doc type for the document.

Then, I though I could use XDoc.write to write to a StrBuf and then call toStr on the buffer. That didn't work either, throwing this error:

sys::UnsupportedErr: binary write on StrBuf output

Next, I tried XDoc.write on a regular Buf, but Buf.toStr doesn't do what I need either. After pushing at it, I finally worked it out with buf.seek(0).readAllStr.

This feels like it's not the best way to do it. Is there an easier way that I have missed? If not, would it be possible to add a convenience method to XDoc or to change the behavior of XDoc.toStr?

EDIT: I realize that it often makes sense to thread XML through streams, but I'm planning on storing XML Documents in a database. Thus, I need a stringifying method to splice the doc into a query.

KevinKelley Wed 14 Oct 2009

Writing an XDoc, you probably ought to need to think about encodings...

But, Fan Str (and StrBuf) use 64-bit chars, so don't need to be encoded. So, it would make sense to go directly from an XDoc to a Str without a lot of hassle.

Using Buf, the "standard" pattern is

buf := Buf() { /*optionally set charset, if going to use raw bytes */ }
doc.write(buf.out)            // write to byte buffer using buf's charset
str := buf.flip.readAllStr    // "flip" from write-mode to read-mode

which isn't horrible, but it would seem that flattening a doc to a Str might be common and useful enough to make a convenience method for that.

So, +1 for XElem.writeStr() or similar -- no opinion on if it should be toStr.

tactics Wed 14 Oct 2009

I didn't know about flip. Neat.

Just out of curiosity, I looked at the code (Fan v1.0.45). Sure enough....

override Str toStr()
{
  return "<?xml version='1.0'?>"
}

brian Wed 14 Oct 2009

The fact that writing to a StrBuf.out raised an exception was a bug. I pushed a fix.

I also added XNode.writeToStr as a convenience.

See changeset

tactics Wed 14 Oct 2009

Awesome. Thanks!

tactics Thu 15 Oct 2009

I got my fan environment up to date just now. I was looking for this change, and I was having trouble finding it. I finally figured it out that you added writeToStr on XNode, not XDoc. I was very confused!

Since a XDoc is just a (docType, rootNode) pair, would it also be possible to put a writeToStr on XDoc that includes the doctype?

class XDoc
{
  ...
  Str writeToStr() 
  {
    docType.toStr + "\n" + root.writeToStr
  }
}

EDIT: The plot thickens. I am looking at the raw source code here. I didn't notice that XDoc was an XElem.

brian Thu 15 Oct 2009

XDoc subclasses XNode, so it should work.

C:\dev\bespin>fansh
Fan Shell v1.0.46 ('?' for help)
fansh> using xml
Add using: using xml
fansh> xml := XDoc()
<?xml version='1.0'?>
fansh> xml.docType = XDocType { systemId = `foo` }
fan.fansh.Var@1d15445 ?= xml.docType
<!DOCTYPE undefined SYSTEM 'foo'>
fansh> xml.writeToStr
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE undefined SYSTEM 'foo'>
<undefined/>

Login or Signup to reply.