diff --git a/README.md b/README.md index 9c60762..2c02887 100644 --- a/README.md +++ b/README.md @@ -468,16 +468,24 @@ For comparing a binary file, simply point the response to the binary file: If the response format is specified as `"type": "xml"` or `"type": "xml2"`, we internally marshal that XML into json using [github.com/clbanning/mxj](https://github.com/clbanning/mxj). -The format `"xml"` uses `NewMapXmlSeq()`, whereas the format `"xml2"` uses `NewMapXml()`, which provides a simpler json format (see also template [`file_xml2json`](#file_xml2json-path)). +The format `"xml"` uses `NewMapXmlSeq()`, whereas the format `"xml2"` uses `NewMapXml()`, which provides a simpler json format. + +See also template [`file_xml2json`](#file_xml2json-path). On that json you can work as you are used to with the json syntax. For seeing how the converted json looks you can use the `--log-verbose` command line flag +## XHTML Data comparison + +If the response format is specified as `"type": "xhtml"`, we internally marshal that XHTML into json using [github.com/clbanning/mxj](https://github.com/clbanning/mxj). + +The XHTML code in the response must comply to the [XHTML standard](https://www.w3.org/TR/xhtml1/), which means it must be parsable as XML. + +See also template [`file_xhtml2json`](#file_xhtml2json-path). + ## CSV Data comparison If the response format is specified as `"type": "csv"`, we internally marshal that CSV into json. -On that json you can work as you are used to with the json syntax. For seeing how the converted json looks you can use the `--log-verbose` command line flag - You can also specify the delimiter (`comma`) for the CSV format (default: `,`): ```yaml @@ -1795,7 +1803,7 @@ int64,string ## `file_xml2json [path]` Helper function to parse an XML file and convert it into json -- `@path`: string; a path to the xml file that should be loaded. The path is either relative to the manifest or a weburl +- `@path`: string; a path to the XML file that should be loaded. The path is either relative to the manifest or a weburl This function uses the function `NewMapXml()` from [github.com/clbanning/mxj](https://github.com/clbanning/mxj). @@ -1847,6 +1855,58 @@ would result in } ``` +## `file_xhtml2json [path]` + +Helper function to parse an XHTML file and convert it into json +- `@path`: string; a path to the XHTML file that should be loaded. The path is either relative to the manifest or a weburl + +### Example + +Content of XHTML file `some/path/example.xhtml`: + +```html + + + + + easydb documentation + + +

Welcome to the easydb documentation

+ + +``` + +The call + +```django +{{ file_xhtml2json "some/path/example.xhtml" }} +``` + +would result in + +```json +{ + "html": { + "-xmlns": "http://www.w3.org/1999/xhtml", + "head": { + "link": { + "-href": "/css/easydb.css", + "-rel": "stylesheet", + "-type": "text/css" + }, + "title": "easydb documentation" + }, + "body": { + "h1": { + "#text": "Welcome to the easydb documentation", + "-id": "welcome-to-the-easydb-documentation" + } + } + } +} +``` + ## `file_sqlite [path] [statement]` Helper function to return the result of an SQL statement from a sqlite3 file. diff --git a/pkg/lib/api/response.go b/pkg/lib/api/response.go index 7f79b63..0aa8306 100755 --- a/pkg/lib/api/response.go +++ b/pkg/lib/api/response.go @@ -83,7 +83,7 @@ type ResponseSerialization struct { type ResponseFormat struct { IgnoreBody bool `json:"-"` // if true, do not try to parse the body (since it is not expected in the response) - Type string `json:"type"` // default "json", allowed: "csv", "json", "xml", "xml2", "binary" + Type string `json:"type"` // default "json", allowed: "csv", "json", "xml", "xml2", "xhtml", "binary" CSV struct { Comma string `json:"comma,omitempty"` } `json:"csv,omitempty"` @@ -170,6 +170,11 @@ func (response Response) ServerResponseToGenericJSON(responseFormat ResponseForm if err != nil { return res, errors.Wrap(err, "Could not marshal xml to json") } + case "xhtml": + bodyData, err = util.Xhtml2Json(resp.Body) + if err != nil { + return res, errors.Wrap(err, "Could not marshal xhtml to json") + } case "csv": runeComma := ',' if responseFormat.CSV.Comma != "" { @@ -376,7 +381,7 @@ func (response Response) ToString() string { body := resp.Body switch resp.Format.Type { - case "xml", "xml2", "csv": + case "xml", "xml2", "csv", "xhtml": if utf8.Valid(body) { bodyString, err = resp.ServerResponseToJsonString(true) if err != nil { diff --git a/pkg/lib/template/template_loader.go b/pkg/lib/template/template_loader.go index 179e895..b16bb9d 100644 --- a/pkg/lib/template/template_loader.go +++ b/pkg/lib/template/template_loader.go @@ -186,6 +186,19 @@ func (loader *Loader) Render( return string(bytes), nil }, + "file_xhtml2json": func(path string) (string, error) { + fileBytes, err := fileReadInternal(path, rootDir) + if err != nil { + return "", err + } + + bytes, err := util.Xhtml2Json(fileBytes) + if err != nil { + return "", errors.Wrap(err, "Could not marshal xhtml to json") + } + + return string(bytes), nil + }, "file_path": func(path string) string { return util.LocalPath(path, rootDir) }, diff --git a/pkg/lib/util/util.go b/pkg/lib/util/util.go index 941d312..fed9916 100644 --- a/pkg/lib/util/util.go +++ b/pkg/lib/util/util.go @@ -75,3 +75,22 @@ func Xml2Json(rawXml []byte, format string) ([]byte, error) { } return json, nil } + +// Xhtml2Json parses the raw xhtml data and converts it into a json string +func Xhtml2Json(rawXhtml []byte) ([]byte, error) { + var ( + mv mxj.Map + err error + ) + + mv, err = mxj.NewMapXml(rawXhtml) + if err != nil { + return []byte{}, errors.Wrap(err, "Could not parse xhtml") + } + + json, err := mv.JsonIndent("", " ") + if err != nil { + return []byte{}, errors.Wrap(err, "Could not convert to json") + } + return json, nil +} diff --git a/test/xhtml/check_local_file_against_response.json b/test/xhtml/check_local_file_against_response.json new file mode 100644 index 0000000..0e6e1e7 --- /dev/null +++ b/test/xhtml/check_local_file_against_response.json @@ -0,0 +1,18 @@ +[ + { + "name": "Get existing XHTML file", + "request": { + "server_url": "{{ datastore "req_base_url" }}", + "endpoint": "bounce-json", + "method": "POST", + "body": {{ file_xhtml2json "sample.xhtml" }} + }, + "response": { + "statuscode": 200, + "body": { + "header": {}, + "body": {{ file "result_xhtml.json" }} + } + } + } +] \ No newline at end of file diff --git a/test/xhtml/check_response_format_xhtml.json b/test/xhtml/check_response_format_xhtml.json new file mode 100644 index 0000000..e8660d9 --- /dev/null +++ b/test/xhtml/check_response_format_xhtml.json @@ -0,0 +1,18 @@ +{ + "name": "bounce XHTML file, use response format \"xhtml\"", + "request": { + "server_url": "{{ datastore "req_base_url" }}", + "endpoint": "bounce", + "method": "POST", + "body": { + "file": "@sample.xhtml" + }, + "body_type": "multipart" + }, + "response": { + "format": { + "type": "xhtml" + }, + "body": {{ file "result_xhtml.json" }} + } +} \ No newline at end of file diff --git a/test/xhtml/manifest.json b/test/xhtml/manifest.json new file mode 100644 index 0000000..f3d66bc --- /dev/null +++ b/test/xhtml/manifest.json @@ -0,0 +1,16 @@ +{{ $local_port:=":9999"}} +{ + "http_server": { + "addr": "{{ $local_port }}", + "dir": "../_res/assets", + "testmode": false + }, + "store": { + "req_base_url": "http://localhost{{ $local_port }}" + }, + "name": "XHTML tests", + "tests": [ + "@check_local_file_against_response.json", + "@check_response_format_xhtml.json" + ] +} \ No newline at end of file diff --git a/test/xhtml/result_xhtml.json b/test/xhtml/result_xhtml.json new file mode 100644 index 0000000..c5b1d7b --- /dev/null +++ b/test/xhtml/result_xhtml.json @@ -0,0 +1,27 @@ +{ + "html": { + "-xmlns": "http://www.w3.org/1999/xhtml", + "head": { + "link": { + "-href": "/css/easydb.css", + "-rel": "stylesheet", + "-type": "text/css" + }, + "title": "easydb documentation" + }, + "body": { + "h1": { + "#text": "Welcome to the easydb documentation", + "-id": "welcome-to-the-easydb-documentation" + }, + "h2": { + "#text": "General", + "-id": "general" + }, + "p": [ + "easydb is a flexible web application that allows customers to manage data and information for images and multimedia.", + "easydb has a flexible data model that allows each instance to be tailored to customer needs." + ] + } + } +} \ No newline at end of file diff --git a/test/xhtml/sample.xhtml b/test/xhtml/sample.xhtml new file mode 100644 index 0000000..908b5cb --- /dev/null +++ b/test/xhtml/sample.xhtml @@ -0,0 +1,21 @@ + + + + + + + easydb documentation + + + + +

Welcome to the easydb documentation

+

General

+

easydb is a flexible web application that allows customers to manage data and information for images and multimedia.

+
+
+

easydb has a flexible data model that allows each instance to be tailored to customer needs.

+
+ + +