Page Bursting

One form of EDDP (Event Driven Document Processing) is "Page Bursting".  Page bursting is only applicable to PDF documents [at least as of the current version].  The purpose of page bursting a document is to decompose a multi-page document into single page documents allowing each page to be easily reviewed individually.  One use case is to scan a large collection of invoices, workorders, receipts, on a document center using a document feeder.  The scanned document can be posted to OpenGroupware Coils via the SMTP service, REST (AttachFS), or WebDAV - whichever the document center supports. If this EDDP feature is configured on the target folder the document will be automatically decomposed into single-page documents.
When a PDF document is created in a folder which either has or inherits a burstingTarget object property in the document management name-space the "coils.blob.event" component will attempt to burst the document into single page documents in the indicated folder. Documents are only page-bursted upon creation.  To achieve page-bursting upon revision use the EDDP auto-file feature to file a copy of the document for every revision into a folder which is configured to perform page-bursting; every auto-filed copy of the document will be a new document and thus eligible for bursting.
The value of the burstingTarget object property must be an ogo:// scheme URI specifying a project and a document path. ogo:// URIs for this usage take the form of "ogo://ProjectNumber/path...?parameters...". If the project resolves but the a corresponding document path does exist the path will be created.
Bursting occurs within the administrative context so the creation of documents in the burst target is controlled only by the permissions to create PDF documents in the origin folder. Only documents of MIME types "application/pdf" or "application/x-pdf" can be page-bursted. Unless the allcopyenabled parameter is appropriately set in the burst target URI unburstable documents will be ignored.  If allcopyenabled has a value of "YES" then unburstable document types will be copied in their entirety to the specified target - object linking and object property inheritance will still be performed as if the new document had been created by bursting.
The handling of documents which are of a burstable type, but for which bursting fails, is controlled by the copyonfailure URI parameter.  By default documents which fail to burst are not copied; setting the copyonfailure parameter to a value of "YES" will cause documents which fail to burst to be copied to the target in their entirety.  When copying documents which failed to burst the target folder can be overridden by setting the errorfolderid parameter to the object id of an alternate folder.  The errorfolderid parameter is only used when the copyonfailure parameter is "YES"; this alternate target is not relevant for non-burstable document types or documents which burst successfully. If a failed document is copied to either the target or an alternate folder object linking and object property inheritance will still be performed as if the new document where created normally – except there will be no reference to the source page.
A notice concerning documents of burstable types for which page bursting failed can be generated to an e-mail address by setting the onfailnotify parameter to a valid e-mail address.  The alert will be generated using the "/Templates/BurstingFailure.mako" Mako template from Project 7,000. Sites may modify this template to match their own requirements. If no corresponding template has been created or the template is invalid an administrative notice will be generated citing the exception which occurred [the intended address will not be notified]. 

  • document - A reference to the source document.
  • folder - A reference to the target folder specified in the target URI.
  • mimetype - The MIME type string of the origin document.
  • copy_on_failure - The value of the copyonfailure parameter from the target URI. 
  • traceback - The trace-back of the exception relating to the failure of the document to be page-bursted.
  • to_address - The value of the onfailnotify parameter from the target URI.  The value will be NULL if no such parameter was specified.
  • copy_enabled - The value of the allcopyenabled parameter from the target URI.
  • error_folder - The value of the errorfolderid parameter from the target URI. The value will be NULL if no such parameter was specified.
Text 1: Template variables provided to the "BurstingFailure.mako" template.
During the attempt to burst a document a timer is enforced for processing each page [this avoids a hung component when dealing with documents that contained damaged or recursive references].  If processing a page of a document exceeds the allowed time the burst operation will be considered a failure and the bursting operation will be rolled back.  Only once all pages have been generated as separate documents will the bursting operation be considered successful.  Upon success or failure of bursting the document an object property of bursted will be set on the source document – a value of "FAIL" indicates bursting of the document failed while a value of "OK" indicates the document was successfully page-bursted.  All documents created by bursting will also have a bursted object property with a value of "TARGET";  this prevents bursting loops in a use-case where a document is page-bursted into a target folder which itself either has or inherits a burstingTarget object property.  The page bursting feature will ignore all documents which have a bursted object property of any value.
Documents of a page-burstable type which fail to burst will also be marked using the "{57c7fc84-3cea-417d-af54-b659eb87a046}damaged" object property with a value of "YES". One effect of this property is to prevent the document from being eligible for EDDP auto-print; a damaged document is not expected to print correctly and depending upon print server configuration may stop the print queue.
Documents created by bursting will have the same file-name, in alpha lower-case, as their origin document but with a "-page-timestamp-random" suffix inserted between the file-name and the file's extension.  For example: from a file named "stanley.agenda.pdf" having three pages documents named:
  1. stanley.agenda-00001-373051543869-92601.pdf
  2. stanley.agenda-00003.373051543869-92601.pdf 
  3. stanley.agenda-00003.373051543869-92601.pdf
will be created in the target path. The purpose of the time-stamp + random is to guarantee file-name uniqueness of the created documents [avoiding overwriting an existing document].  The page counter is limited to five digits - creating an effective maximum document length of 9,999 pages, page bursting of documents with more then 9,999 pages is not supported.Each document created by bursting will have three object properties in the document management name-space: the bursted property described previously,  sourceDocumentId with a value of the object id of the source document and sourceDocumentPage with a value of the page number the document represents from the source document.  These properties are added to the collection of any object properties existed on the source document.  In order to preserve all meta-data throughout the life-cycle of the document all documents created by page bursting initially inherit copies of all the object properties and object links which exist relating to the source document.  The properties applied by the bursting operation are then applied to the set properties copied from the source document [potentially over-writing an inherited object property].
In addition to the object properties the following actions are performed on documents created by page bursting – regardless of if the generated documents are pages from page-burstable document types or copies of non-page-burstable types due the to allcopyenabled feature.

  1. An object-link having a type of coils:burstedFrom will be created where the source of the link is the single-page document and the target of the link is the original [potentially multi-page] document.  This link is intended to facilitate easily generated mapping of a document's provenance and life-cycle.
  2. Audit messages of type comment are made on the new documents stating their origin.  This makes the provenance of the documents readily visible to end-users.  If the document was successfully page-bursted [from a page-burstable document type] the audit comment indicates the page number to which the document corresponds; audit comments on non-page-burstable documents copied due to the allcopyenabled feature or documents which failed to burst which were copied due to the copyonfailure feature will not reference a page number, only the identity of the original document.
The document uploaded and page-bursted will remain in the folder to which it was uploaded. Since bursting occurs due to an event on the entity exchange it is not transactional - failure of the document to burst will not result in failure of the upload of the document.  There is also a potential opportunity that a document uploaded to a folder with a bursting target may be deleted before page bursting can occur – this will not result in an error, non-existent documents [documents which have been deleted] are ignored by the coils.blob.event service.  If it is necessary to avoid the case where a document must be page-bursted in all circumstances delete and pare permissions should be removed from the folder regarding the security context performing the upload.  Expiration of documents from the source folders, if they are not required, is best managed using document retention policies.


Event Driven Document Processing

OpenGroupware Coils provides support for Event Driven Document Processing (EDDP).  EDDP exploits the OpenGroupware's underlying message oriented model to allow for rapidly and efficiently performing transactions based upon document creation or modification.  All entity related events are announced on the server's entity event exchange for any interested component to receive - events related to documents are collected by the coils.blob.event component.
OpenGroupware Coils currently [as of 0.1.49rc81] supports the following EDDP features:
  1. Document auto-collection.  Documents created in a specified folder hierarchy can be automatically assigned to a Collection entity.  
  2. Document auto-uncollection.  Once a document is assigned certain properties the document can be automatically removed from a Collection entity.
  3. Automated filing of new and revised documents.  When a document is created or updated a copy of the document, or the current revision of the document, can be automatically copied as a new document to another location.  The copied document will retain all the meta-data of the original document as well as being connected to the original via an object link entity.
  4. PDF documents created or revised can be page bursted created a new document in a specified located representing each page of the source document.
  5. Documents created can be automatically submitted to an IPP queue for printing.
  6. Invocation of work-flow processes when documents are created or revising withing a folder hierarchy.  The documentation refers to this feature as "Special Processing" as it ties the open-ended flexibility of the OpenGroupware Integration Engine with document management.
One key aspect of EDDP is that event driven document actions can be daisy-chained.  For example a folder can be configured to have new documents of type PDF page-bursted into another folder, the target folder of the page bursting action can itself be configured to auto-collect created within to be auto-collected.  An application can then easily present a list of pages for review to a user - when the user reviews a page the act of applying a object property value to the document can cause the document to be automatically removed from the `to be reviewed` collection.  By using the EDDP features of OpenGroupware Coils the application only needs to be concerned with retrieving the list of documents to be reviewed and applying an appropriate object property to the document [just two RPC operations - not counting the retrieval of the single page document for presenting to the user].  Multiple operations can be applied to a single folder - a folder could be configured to, for example, auto-file a new document to a specified location as well as automatically queue the document for printing.
In the upcoming day's we will look at each of the EDDP features in detail.  If you can't wait all these features are documented in the current edition of WMOGAG.

Aside: At this time [as of 0.1.49rc81] the auto-print feature for new and update documents utilizes the same entity event exchange but it implemented as a separate service component: "coils.blob.autoprint".  In time auto-print will hopefully be rolled into the coils.blob.event component to make a single component for processing document related events.  Auto-print was the first component to utilize the entity event exchange concept and being a bit of an experiment was developed as a stand-alone component;  coils.blob.event was developed subsequently to manage the range of EDDP functions supported by OpenGroupware Coils.  The coils.vista.index and coils.blob.autothumb also process document related events but are unrelated to EDDP.


Document MIME Types & MIME Type Rewriting

OpenGroupware Coils records the MIME type of a document, as provided by the client which creates it, as the object property "{57c7fc84-3cea-417d-af54-b659eb87a046}contentType".  In the case of a WebDAV, or any standards compliant HTTP client, this will be the value of the Content-Type header of the HTTP PUT operation. The value of this object property is used when the content-type is presented to any subsequent client.
If the content-type property does not exist or has a value of any of "application/octet-string”, "application/octet-steam”, or "binary/octet-stream” a guess of the type will be attempted based on the extension [if any] of the file-name.  For example: if a document has no content-type property but the file-name of the document is "stanley.pdf” the server will assume the document has a MIME-type of "application/pdf”.  The guess based on the file extension uses the server's CoilsExtensionMIMEMap default – this default is a dictionary which maps file extensions to PDFs.

MIME-Type Rewriting

Additionally, when presenting a document to a client, the server will check the MIME-type against the dictionary stored in the server's CoilsMIMETypeRewriteMap default.  This default is used to implement MIME-type rewriting.  Some clients may upload content using an invalid or obsolete MIME-type.  For example a client may upload a document with a MIME-type of "image/pdf”.  "image/pdf” is not a standard MIME-type and other clients may not deal with it properly - via MIME-type rewriting the server will present this MIME-type as "application/pdf” to subsequent client requests.  If MIME-type rewriting is enabled for the MIME-type specified in an upload the rewritten MIME-type is included as the Content-Type header value of the upload response.  MIME-type rewrite support is implemented for the Omphalos "mimetype” attribute of the "File” entity used by JSON-RPC and XML-RPC as well as in AttachFS and WebDAV protocols.  Sites may override the built-in value of the CoilsMIMETypeRewriteMap default if they have additional MIME-types that require rewriting – if overriden the value must be a complete dictionary of types to rewrite, an site setting of the default replaces the built-in value, it is not additive.
{'image/pdf': 'application/pdf',
  'application/x-pdf': 'application/pdf',
  'applications/vnd.pdf': 'application/pdf',
  'text/pdf': 'application/pdf',
  'text/x-pdf': 'application/pdf',
  'application/acrobat': 'application/pdf',
  'binary/octet-stream': 'application/octet-stream', }

Text 1: The out-of-the-box value of the CoilsMIMETypeRewriteMap default.
Regardless of any rewriting of the MIME-type the server always stores the MIME-type as it was provided by the original request [at least until it is explicitly changed].


Object Property Aliases

  namespace: http://www.example.com/service
  attribute: workorder
  namespace: http://www.example.com/document
  attribute: documentType

Text 1: Defines two property aliases; "workorder" = "{http://www.example.com/service}workorder" and "documentType" = "{http://www.example.com/document}documentType".
Property aliases, defined in "/dav/Administration/PropertyAliases.yaml" provide short names for object properties. Primarily property aliases are used when storing documents via AttachFS when some meta-data needs to be stored along with the document. Use of property aliases is also supported for constructing the file-to path when a document is processed for auto-filing.
The normal representation of an object property's use of name-spaces makes specification of the property in a URI parameter cumbersome and unreliable. By allowing properties to be aliased to short-names they can be referenced more easily. It is expected that most object properties will not be aliases, but only those for which it is useful to refer to in URIs, etc...
In the upload URI for an AttachFS PUT the object property aliases can be referenced as parameters by using a "pa." prefix on the alias [object property aliases are case-sensitive]. An object property specified in the URL using a "pa." prefix but having no value will be assigned a value of "YES".
$ curl -u adam -T snapper.log -H 'Content-Type: text/plain' \ 'http://coils.example.com/attachfs/30330610/george.txt?mode=file&pa.workorder=123456&pa.documentType=note'
Text 2: Upload the document "george.txt" and setting object property values for the object properites with the aliases of "workorder" and "documentType".
Aside: In addition to setting defined object properties the URL parameters "abstract", "appointment", and "company" may be used to set the corresponding attributes of a document entity [when you are uploading a document via AttachFS]. "abstract" must be a string, this sets the long human-readable description of the document. "appointment" and "company" values must be integers; these set the linkage attributes of the document to establish a 1:1 relation between the specified entity and the document. Assigning a non-integer value to "appointment" or "company" parameters will result in an exception and the AttachFS opertation will fail; but beyond the type of the value the server does not validate that the provided value refers to an available appointment or company [contact or enterprise] entity. A client may discover object-property aliases by providing the alias information in the "DefinedProperties.yaml" file using the "alias" field of the defined property description.


OpenGrouwpare As A CUPS Backend

A script suitable for use as a back-end for the CUPS print server package is included with OpenGroupware Coils. This back-end allows for queues to be created that perform HTTP PUT requests to the server using configurable [per queue] paths.  Using OpenGroupware Coils as a CUPS back-end easily enables client applications - and any application - to submit documents to work-flows or to store documents in project folders; the client simply prints via a print queue using a Postscript print driver and the CUPS server converts the document to PDF and pushes it to the server using the specified path.  An example of this is a receipt printer - printing to a project document folder allows the document to be filed electronically;  event driven document processing can then turn that same PDF around and submit it to an actual print queue if necessary.

To install the CUPs backend copy the “cups-to-ogo” script to the appropriate back-end directory on the print server and modify the permissions to permit the script to be executed by the CUPs user [typically “lp” or “root”]. 
This script does not require OpenGroupware components or the OpenGroupware package to be installed on the print server; all Python requirements are satisfied by the Python standard library.
A tool such as “ps2pdf” for converting Postscript to PDF will also be required; the script assumes all content posted to the server is in PDF format. These tools are generally already installed on any CUPS instance as CUPS itself uses the ghostscript tool-chain for processing the content of jobs.
When the script is executed by the CUPS server it will log messages to the local syslog server under the LPR facilty.


Text 2: An example cups-to-ogo.ini configuration file.
The script will attempt to read it's configuration from an INI file located at “/etc/cups/cups-to-ogo.ini”. This location may be overridden by setting the environment variable OGOCUPSCONFIGINI to the full path of the required INI file; in order to be effective that environment variable must be present in the environment of the CUPS server itself – the environment of the server is inherited by all filters and back-ends executed by the CUPS instance.
The INI file has a single global section. This section specifies the URI of the OpenGroupware Coils server, the authentication information , and the path to the postscript to PDF conversion tool. 
Section Parameter Description
The base URI to the OpenGroupware COILS server. This URI should end with a “/”.
The authentication mechanism to use when authenticating to the server; at this time only “plain” is supported.
The path to the executable postscript to PDF conversion tool. This tool must read its input from standard-input and write the converted document to standard-output. The tool must also be executable within the context of the CUPS server instance.
If auth_mech is “plain” this specifies the user-name to use when performing BASIC authentication to the CUPS server.
If auth_mech is “plain” this specifies the password to use when performing BASIC authentication to the CUPS server.
Table 2: cups-to-ogo configuration parameters supported in the cups-to-ogo.ini file.
Once the script has been installed and configured it should be reported when listing the enabled CUPS back-ends using the “lpinfo -v” command on the print server. 

$ lpinfo -v
network ipp
network socket
direct scsi
network smb
network http
network lpd
network beh
network https
serial serial:/dev/ttyS0?baud=115200
serial serial:/dev/ttyS1?baud=115200

network cups-to-ogo

network socket://

Text 3: Listing the available CUPS back-ends using "lpinfo -v"
When defining a target to receive documents from the CUPS integration do not forget to provision security ACLs of the resource to make it accessible to the user which the back-end authenticates as. In order to create a document within a folder the CUPS context must be able to realize the folder's project and have been granted list and insert permissions on the target folder.
It is recommended that a site create a specific intranet account for use by the CUPS server for authenticating to the OpenGroupware instance; this facilitates change control and auditing. This special purpose account should be excluded from the all-intranet team to avoid the possibility of inheriting additional privileges. The CUPS server should never be provided with the OpenGroupware administrative credentials or any credentials holding an administrative or developer role. Authentication and access control related to queuing jobs to queues defined on the CUPS server is entirely an issue relating to the administration and configuration of the CUPS instance,.
Creating Queues

Queues for pushing documents to the OpenGroupware Coils server can created using either the CUPS web interface or the lpadmin command line tool.
The recommended CUPS print driver for all cups-to-ogo queues is “Generic PostScript Printer Foomatic/Postscript”. The postscript input job will be converted to PDF using the configured conversion tool.
Illustration 1: CUPS web interface for creating a new print queue, via "Add Printer".
The utility of the cups-to-ogo backend is exercised through the URL portion of the printer definition. The URI specified for the queue is appended to the server URI provided in the INI configuration file. The print job, after being converted to PDF format, will be uploaded to the resulting URL by an HTTP PUT operation. Utilizing the standard HTTP PUT operation allows documents to be submitted to work-flow routes, uploaded via AttachFS, or placed in WebDAV collections.
In order to facilitate uploads into collections, via either AttachFS or WebDAV, as well as to allow capturing of all source meta-data replacement labels may be placed in the queue's URI.  These strings have the form of “${label}” where label is the label name;  each label in the queue's URI will be replaced with the appropriate value when a job is processed.
For example, to submit a print job [converted to a PDF document] to a work-flow route named “MailMeExample” and include the user name of the user who submitted the job to the CUPS server a queue URI of “cups-to-ogo://dav/Workflow­/Routes/MailMeExample/input?username=${user}” would be used. The content of the print job would be the input message of the new process [instance of the work-flow route] and an XATTR named “username” would be created and attached to the process, the value of that XATTR would be the name of the username of the user who authenticated to the CUPS server. 
Label Description
The user name of the context which submitted the print job [and potentially authenticated to the CUPS server]. This value will be URL quoted when the URL is constructed as user names may contain punctuation and whitespace.
The job id assigned to the job by the CUPS server.
The title attribute of the print job. This value will be URL quoted when the URL is constructed as job titles may contain punctuation and whitespace.
Generates a GUID string. This is intended for use-cases when a unique identifier is required within the PUT URI.

Text 4: Substitution labels supported by the cups-to-ogo backend.

Another common use for the CUPS backend is to auto-file jobs to project folders. This can be accomplished by setting the URI of the queue to an AttachFS target indicating the folder in which to file the document. Note that auto-filing, auto-printing, etc... are still effective – those services do no consider the origin of the document. In order to file a document into a project folder with an object id of 8,891,874 a queue should be created with a URI of “cups-to-ogo:// attachfs/8891874/${guid}.pdf?mode=file”. Note how this is a standard AttachFS URI; the file mode is specified since we desire to create a document rather than an attachment. A unique file name within the folder is required so the guid substitution label is used; from this URI a unique named document will be created with a “pdf” file extension.
  attribute: cupsJobUser
  namespace: 57c7fc84-3cea-417d-af54-b659eb87a046


  attribute: cupsJobTitle
  namespace: 57c7fc84-3cea-417d-af54-b659eb87a046


  attribute: cupsJobId
  namespace: 57c7fc84-3cea-417d-af54-b659eb87a046
Text 5: Example for adding the three CUPS meta-data related properties to the server's object property alias map.
Three object-properties have been defined in the document management name-space intended to contain the CUPS job information. To expose these properties for use in AttachFS URIs add them to the property aliases map of the server. If the properties are exposed as the default aliases the additional meta-data can be recorded as object properties of the new document by extending the URI of the previous example to “cups-to-ogo://attachfs/8891874/${guid}.pdf?mode=file&pa.cupsJobId=${id}&pa.cupsJobUser=${user}&pa.cupsJobTitle=${title}”.

When the script is executed by the CUPS server it will log messages to the local syslog server under the LPR facilty.
Provided the back-end attempts to submit a job to the OpenGroupware server – meaning the input for the filter was processed successfully – the result provided back to the CUPS server will depend upon the server's response to the HTTP PUT.
A success response, any of 200 [OK], 201 [Created], 202 [Accepted], 204 [No Content], or 301 [Moved Permanently] result in a status 0 [OK] to the CUPS server indicating the job was successfully processed and the server may proceed to the next job.
A server response of 401 [Authentication Required], 419 [Authentication Time Out], 511 [Network Authentication Required], 496 [No Certificate], or 495 [Certificate Error] results in a status of 2 [Authenticated Required2] indicating to the CUPS server than an authentication or identity related issue occurred. CUPS will place the job on hold and add the “cups-held-for-authentication” keyword to the “jobs-reasons” CUPS job attribute.
If the server response indicates a temporary error by responding with 423 [Locked (WebDAV)], 409 [Conflict], 408 [Request Timeout], or 429 [Too Many Requests (Back Off)] the CUPS status of 6 [Retry] will be returned. This status indicates the CUPS server may retry the job at a later time; the server may still proceed to processing the next job in the queue.
A response value of either 418 [Teapot] or 451 [Unavailable For Legal Reasons] will result in CUPS status 5 [Cancel]. The CUPS server responds to a status 5 by automatically canceling the current job and proceeding to the next job.
Any other server response, most notably a 404 [Not Found] or 500 [Server Error], will return status 1 [Failed] to the server. The server will respond to this status using the queues defined error-policy attribute. Generally speaking the CUPS default error policy is to change the queue to a paused state when encountering a status 1 [Failed] response; a paused queue will continue to accept jobs but will not attempt to submit them to the backend.


Getting A Route's Markup Via AttachFS

AttachFS provides a simple method to retrieve the representation or contents of an entity via a GET request for the object's identifier [even improper entities such as messages and attachments can be retrieved this way].  For simple clients this is often a more straight forward approach than WebDAV.
As of 0.1.49rc70 you can now retrieve the BPML markup of an OIE workflow by requesting the route's object id from AttachFS.

$ curl -vvv -u ogo:fred123 http://coils.example.com/attachfs/view/161560
> GET /attachfs/view/161560 HTTP/1.1

< Content-Length: 4228
< Content-Type: text/xml
< Set-Cookie: OGOCOILSESSIONID=20822efa-c714-40bb-bd17-283b6466e049-4cb5a34a-74cd-4c3e-9d1b-9f92382b2820-52d38676-c9ec-41f7-968d-add83df842ad; Domain=www.example.com; expires=Mon, 16-Dec-2013 23:34:21 UTC; Path=/
< X-OpenGroupware-Filename: V388TmpxrefrLoad.bpml
< etag: 161560:1
< Connection: close
<?xml version="1.0" encoding="UTF-8"?>

Example response when requesting the object id 161,560 using AttachFS.  This is a route so the markup is returned.  Note the inclusion of the X-OpenGroupware-Filename as well as the etag.


StandardXML To JSON

The latest commits to OpenGroupware Coils add a new jsonWriteAction action for zOIE workflows.  OIE has long as readJSON for serializing arbitrary JSON documents into XML.  jsonWriteAction adds the ability to serialize StandardXML data into JSON documents [provided all the data-types represented in the StandardXML document can be persisted in JSON].  Date and date time values will be serialized as strings in the "YYYY-MM-DDTHH:MM:SS" format; date values will have a time value of "00:00:00'".  The jsonWriteAction requires no parameters - it simply transfoms the entire input message into JSON.

<action name="actionActivity" id="00020" extensionAttributes="XLSToJSONMailBack/00020">
  <input property="JSONData" formatter="StandardRaw"/>
  <output><source property="XLSData"/></output>
    <extension name="activityName">writeJSONAction</extension>

Text 1: The contents of the message "XLSData" is serialized to an application/json message labeled "JSONData".

The row elements from the StandardXML data stream will persisted into the rows key of the JSON document with each element of that array containing a keys and fields array.  Keys contain the attributes of the row which where indicated to be primary keys while fields contains the non-idempotent field values.  This maintains the meta-data at least of the record identity which in StandardXML would be encoded in element attributes [JSON having no concept of value attributes cannot express this information].
 {"formatClass": null,
 "formatName": null,
 "rows": [
     {"keys": {},
      "fields": {
        "comment": null,
        "fs_net_price": 72.0,
        "fs_discount": 0.4,
        "dexription": "Brace",
        "no_": "000-0005",
        "x2011_list": 120.0}},
     {"keys": {},
      "fields": {
        "comment": null,
        "fs_net_price": 85.98,
        "fs_discount": 0.4,
        "dexription": "Diamond Brush Template, 13\"",
        "no_": "000-0010",
        "x2011_list": 143.3}} ]
 "tableName": null,
 "rowCount": 6330}

Text 2:A JSON representation of a StandardXML message created via the xlsToXmlAction - a message having no format name, format class,  or target/source table.  No elements of the row are indicated to be keys so all columns are represented as fields.
The target/source table as well as the format information will be presented in the JSON data as outermost keys.  If the StandardXML was generated from arbitrary XML [such as the use of xlsToXmlAction] these fields may be null.   The total row count is also presented as an outermost key avoiding the need to clients to iterate the entire value of rows in order to present a count.
Thanks to the new writeJSONAction the job of shipping row and field oriented data off to a web application is now trivial.