diff --git a/.gitignore b/.gitignore
index ab3e096..4a86338 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,5 @@
.vscode
nbactions.xml
target/
+__pycache__
+venv
diff --git a/Backend-libXML/.gitignore b/Backend-libXML/.gitignore
new file mode 100644
index 0000000..9ca9383
--- /dev/null
+++ b/Backend-libXML/.gitignore
@@ -0,0 +1,3 @@
+.idea
+__pycache**
+venv
diff --git a/Backend-libXML/Dockerfile b/Backend-libXML/Dockerfile
new file mode 100644
index 0000000..f3524b4
--- /dev/null
+++ b/Backend-libXML/Dockerfile
@@ -0,0 +1,8 @@
+FROM tiangolo/meinheld-gunicorn-flask:python3.9
+
+COPY ./requirements.txt /app/requirements.txt
+
+RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
+
+COPY ./main.py /app/
+COPY ./Parser.py /app/
\ No newline at end of file
diff --git a/Backend-libXML/Parser.py b/Backend-libXML/Parser.py
new file mode 100644
index 0000000..3b492b1
--- /dev/null
+++ b/Backend-libXML/Parser.py
@@ -0,0 +1,67 @@
+from lxml import etree
+
+
+def xpath(source: str, xpath: str) -> str:
+ """
+ Method used to get nodes from XML string using XPath
+
+ :param source: XML string used for selection
+ :type source: str
+ :param xpath: XPath query used for selection
+ :type xpath: str
+ :return: Nodes selected using XPath
+ :rtype: str
+ """
+
+
+ root = etree.XML(source)
+ nsmap = root.nsmap
+
+ # LXML doesn't accept empty (None) namespace prefix,
+ # so it need to be deleted if exists
+ if None in nsmap:
+ nsmap.pop(None)
+
+ result = root.xpath(xpath, namespaces=nsmap)
+ result_string = ""
+ for e in result:
+ result_string += etree.tostring(e, pretty_print=True).decode() + "\n"
+ return result_string
+
+
+
+def xsd(source: str, xsd: str) -> bool:
+ """
+ Method used to validate XML string against XSD schema
+ :param source: XML string used for validation
+ :type source: str
+ :param xsd: XSD schema to validate XML against
+ :type xsd: str
+ :return: If the validation was successful or not
+ :rtype: bool
+ """
+ xml_schema = etree.XMLSchema(etree.XML(xsd))
+
+ xml = etree.XML(source)
+
+ return xml_schema.validate(xml)
+
+
+def xslt(source: str, xslt: str) -> str:
+ """
+ Method used to transformate XML string using XSLT
+
+ :param source: XML string to transform
+ :type source: str
+ :param xslt: XSLT string used to transformate XML
+ :type xslt: str
+ :return: Result of transformation
+ :rtype: str
+ """
+ xslt_transform = etree.XSLT(etree.XML(xslt))
+
+ xml = etree.XML(source)
+
+ transformated = xslt_transform(xml)
+ print(transformated)
+ return str(transformated)
\ No newline at end of file
diff --git a/Backend-libXML/main.py b/Backend-libXML/main.py
new file mode 100644
index 0000000..78fc6cf
--- /dev/null
+++ b/Backend-libXML/main.py
@@ -0,0 +1,68 @@
+from flask import Flask
+from flask import request
+from lxml import etree
+import json
+import time
+import Parser
+
+
+app = Flask(__name__)
+
+
+def process_xml(request: request, type: str) -> str:
+ """Function to process
+
+ :param request: Received request
+ :type request: request
+ :param type: Type of needed processing: xsd, xslt or xpath
+ :type type: str
+ :raises ValueError: is raised when type is different than those provided above
+ :return: response JSON converted to string and response code
+ :rtype: str, int
+ """
+ start = time.time_ns()
+ code = 200
+ response_json = dict()
+ try:
+ request_data = json.loads(request.get_data(as_text=True))
+ data = request_data['data']
+ process = request_data['process']
+ if (type == "xsd"):
+ response_json['result'] = Parser.xsd(data, process)
+ elif (type == "xslt"):
+ response_json['result'] = Parser.xslt(data, process)
+ elif (type == "xpath"):
+ response_json['result'] = Parser.xpath(data, process)
+ else:
+ raise ValueError("Valid operation types are: xsd, xslt, xpath")
+
+ response_json['status'] = "OK"
+ except KeyError as e:
+ response_json['result'] = "Missing key: " + str(e)
+ response_json['status'] = "ERR"
+ code = 400
+ except Exception as e:
+ response_json['result'] = str(e)
+ response_json['status'] = "ERR"
+ code = 400
+ finally:
+ exec_time = (time.time_ns() - start) / 10**6
+ response_json['time'] = f"{exec_time:.03f}"
+ response_json['processor'] = "libxml2 over lxml"
+ return json.dumps(response_json), code
+
+
+@app.route("/xpathpost", methods=["POST"])
+def xpath():
+ return process_xml(request, "xpath")
+
+@app.route("/xsdpost", methods=["POST"])
+def xsd():
+ return process_xml(request, "xsd")
+
+@app.route("/xsltpost", methods=["POST"])
+def xslt():
+ return process_xml(request, "xslt")
+
+if __name__ == "__main__":
+ app.run()
\ No newline at end of file
diff --git a/Backend-libXML/requirements.txt b/Backend-libXML/requirements.txt
new file mode 100644
index 0000000..d176ffe
--- /dev/null
+++ b/Backend-libXML/requirements.txt
@@ -0,0 +1,2 @@
+lxml
+flask
diff --git a/Backend-libXML/sample/xpath/data.json b/Backend-libXML/sample/xpath/data.json
new file mode 100644
index 0000000..2de1632
--- /dev/null
+++ b/Backend-libXML/sample/xpath/data.json
@@ -0,0 +1,6 @@
+{
+ "data": "Hamlet 2001-05-04 1 false Macbeth 2000-12-13 1 false Harry Potter and the Sorcerer's Stone 2005-04-29 2 true The Long Walk 2018-07-01 4 true Misery 2018-01-31 4 true Think and Grow Rich 2004-09-10 6 true The Law of Success 1982-05-09 6 false Patriot Games 1995-10-21 5 false The Sum of All Fears 1992-09-19 5 false The Alchemist 2017-02-20 3 false Hamlet 1994-06-01 1 false Measure for Measure 1990-03-23 1 false Hamlet 1989-05-05 1 true Hamlet 1999-05-30 1 true The Law of Success 2004-11-26 6 true Romeo and Juliet 1997-02-08 1 true The Alchemist 2009-08-21 3 true ",
+ "process": "/books/book[name = 'The Law of Success']",
+ "processor": "saxon",
+ "version": "2.0"
+}
diff --git a/Backend-libXML/sample/xpath/dataNS.json b/Backend-libXML/sample/xpath/dataNS.json
new file mode 100644
index 0000000..ec5eb94
--- /dev/null
+++ b/Backend-libXML/sample/xpath/dataNS.json
@@ -0,0 +1,6 @@
+{
+ "data": "Hamlet 2001-05-04 1 false Macbeth 2000-12-13 1 false Harry Potter and the Sorcerer's Stone 2005-04-29 2 true The Long Walk 2018-07-01 4 true Misery 2018-01-31 4 true Think and Grow Rich 2004-09-10 6 true The Law of Success 1982-05-09 6 false Patriot Games 1995-10-21 5 false The Sum of All Fears 1992-09-19 5 false The Alchemist 2017-02-20 3 false Hamlet 1994-06-01 1 false Measure for Measure 1990-03-23 1 false Hamlet 1989-05-05 1 true Hamlet 1999-05-30 1 true The Law of Success 2004-11-26 6 true Romeo and Juliet 1997-02-08 1 true The Alchemist 2009-08-21 3 true ",
+ "process": "/b:books/b:book[b:name = 'The Law of Success']",
+ "processor": "saxon",
+ "version": "2.0"
+}
diff --git a/Backend-libXML/sample/xpath/non-ns.curl b/Backend-libXML/sample/xpath/non-ns.curl
new file mode 100644
index 0000000..7d4219f
--- /dev/null
+++ b/Backend-libXML/sample/xpath/non-ns.curl
@@ -0,0 +1,4 @@
+#url = "localhost:8081/xpathpost"
+url = "localhost:5000/xpath"
+request = "POST"
+data = "@data.json"
diff --git a/Backend-libXML/sample/xpath/ns.curl b/Backend-libXML/sample/xpath/ns.curl
new file mode 100644
index 0000000..f439c0e
--- /dev/null
+++ b/Backend-libXML/sample/xpath/ns.curl
@@ -0,0 +1,4 @@
+#url = "localhost:8081/xpathpost"
+url = "localhost:5000/xpath"
+request = "POST"
+data = "@dataNS.json"
diff --git a/Backend-libXML/sample/xsd/xsd.curl b/Backend-libXML/sample/xsd/xsd.curl
new file mode 100644
index 0000000..2481c02
--- /dev/null
+++ b/Backend-libXML/sample/xsd/xsd.curl
@@ -0,0 +1,4 @@
+#url = "http://localhost:8082/xsd"
+url = "http://localhost:5000/xsd"
+data = "@xsd.json"
+request = POST
diff --git a/Backend-libXML/sample/xsd/xsd.json b/Backend-libXML/sample/xsd/xsd.json
new file mode 100644
index 0000000..91dd2f2
--- /dev/null
+++ b/Backend-libXML/sample/xsd/xsd.json
@@ -0,0 +1,6 @@
+{
+ "data": "Test Test3 ",
+ "process": " ",
+ "processor": "saxon",
+ "version": "1.0"
+}
diff --git a/Backend-libXML/sample/xslt/xslt.curl b/Backend-libXML/sample/xslt/xslt.curl
new file mode 100644
index 0000000..d50edd1
--- /dev/null
+++ b/Backend-libXML/sample/xslt/xslt.curl
@@ -0,0 +1,3 @@
+url = "http://localhost:5000/xslt"
+data = "@xslt.json"
+request = POST
diff --git a/Backend-libXML/sample/xslt/xslt.json b/Backend-libXML/sample/xslt/xslt.json
new file mode 100644
index 0000000..f833a40
--- /dev/null
+++ b/Backend-libXML/sample/xslt/xslt.json
@@ -0,0 +1,6 @@
+{
+ "data": "Hamlet 2001-05-04 1 false Macbeth 2000-12-13 1 false Harry Potter and the Sorcerer's Stone 2005-04-29 2 true The Long Walk 2018-07-01 4 true Misery 2018-01-31 4 true Think and Grow Rich 2004-09-10 6 true The Law of Success 1982-05-09 6 false Patriot Games 1995-10-21 5 false The Sum of All Fears 1992-09-19 5 false The Alchemist 2017-02-20 3 false Hamlet 1994-06-01 1 false Measure for Measure 1990-03-23 1 false Hamlet 1989-05-05 1 true Hamlet 1999-05-30 1 true The Law of Success 2004-11-26 6 true Romeo and Juliet 1997-02-08 1 true The Alchemist 2009-08-21 3 true ",
+ "process": " ",
+ "processor": "saxon",
+ "version": "1.0"
+}
diff --git a/Backend/mocked-services/src/main/resources/static/html/mock.html b/Backend/mocked-services/src/main/resources/static/html/mock.html
index 79f52b4..f597720 100644
--- a/Backend/mocked-services/src/main/resources/static/html/mock.html
+++ b/Backend/mocked-services/src/main/resources/static/html/mock.html
@@ -8,6 +8,7 @@
+
diff --git a/Backend/mocked-services/src/main/resources/static/js/dyn_host.js b/Backend/mocked-services/src/main/resources/static/js/dyn_host.js
new file mode 100644
index 0000000..b13a6e1
--- /dev/null
+++ b/Backend/mocked-services/src/main/resources/static/js/dyn_host.js
@@ -0,0 +1,11 @@
+$(document).ready( function() {
+ console.log("Here")
+ let links = document.getElementsByTagName("link")
+ for (let i = 0; i < links.length; i++) {
+ let oldStr = links[i].href.split("/")
+ let endpoint = oldStr.slice(3).join("/")
+ links[i].href = window.location.protocol + "//" + window.location.hostname + ":8086/" + endpoint
+ }
+
+});
+
diff --git a/Frontend/assets/scripts/tools/jquery-3.6.0.slim.min.js b/Frontend/assets/scripts/common/jquery-3.6.0.slim.min.js
similarity index 100%
rename from Frontend/assets/scripts/tools/jquery-3.6.0.slim.min.js
rename to Frontend/assets/scripts/common/jquery-3.6.0.slim.min.js
diff --git a/Frontend/assets/scripts/dyn_host.js b/Frontend/assets/scripts/dyn_host.js
new file mode 100644
index 0000000..0a1110f
--- /dev/null
+++ b/Frontend/assets/scripts/dyn_host.js
@@ -0,0 +1,8 @@
+$(document).ready( function() {
+ document.getElementsByName("iframe")[0].src =
+ window.location.protocol + "//" + window.location.hostname + ":8097";
+ document.getElementById("rest-mock").href =
+ window.location.protocol + "//" + window.location.hostname + ":8097";
+ console.log("DONE")
+});
+
\ No newline at end of file
diff --git a/Frontend/assets/scripts/tools/scripts.js b/Frontend/assets/scripts/tools/scripts.js
index f0ced97..23818b3 100644
--- a/Frontend/assets/scripts/tools/scripts.js
+++ b/Frontend/assets/scripts/tools/scripts.js
@@ -106,7 +106,7 @@ function performRequest(text, checkXML, checkTransform){
async function restRequest(text) {
const escapeChar = "specialEscapeChar";
// const addr = "http://localhost:8081/" + text;
- const addr = "http://tools.zipper.release11.com" + text;
+ const addr = window.location.protocol + "//" + window.location.hostname + ":8081/" + text;
var xmlData = document.getElementById("xmlArea").value.trim();
var transformData = document.getElementById("transformArea").value.trim();
diff --git a/Frontend/index.html b/Frontend/index.html
index 0bb9ddf..a5647f6 100644
--- a/Frontend/index.html
+++ b/Frontend/index.html
@@ -4,8 +4,12 @@
+
+
+
-
+
+
@@ -16,16 +20,20 @@
+
+
diff --git a/Frontend/tools/xpath.html b/Frontend/tools/xpath.html
index 3d0a6b3..1d4a84d 100644
--- a/Frontend/tools/xpath.html
+++ b/Frontend/tools/xpath.html
@@ -24,7 +24,7 @@
Select XPath processor:
Saxon
-
+ libXML
XPath version:
diff --git a/Frontend/tools/xsd.html b/Frontend/tools/xsd.html
index 3e61029..84234bf 100644
--- a/Frontend/tools/xsd.html
+++ b/Frontend/tools/xsd.html
@@ -18,8 +18,8 @@
Select XSLT processor:
-
Xalan
+ libXML
diff --git a/Frontend/tools/xslt.html b/Frontend/tools/xslt.html
index cc77f34..f1656e9 100644
--- a/Frontend/tools/xslt.html
+++ b/Frontend/tools/xslt.html
@@ -19,6 +19,7 @@
Saxon
Xalan
+ libXML
procInfo
diff --git a/docker-compose.yml b/docker-compose.yml
index 559be61..6524db5 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -19,6 +19,13 @@ services:
ports:
- 8081:8081
+ xmltools-libxml-backend:
+ build: ./Backend-libXML
+ container_name: xmltools-libxml-backend
+ image: xmltools-libxml-backend
+ ports:
+ - 8082:80
+
xmltools-mocked-services:
build:
context: ./Backend/mocked-services
diff --git a/readme.md b/readme.md
index d5600b6..c1a3e1b 100644
--- a/readme.md
+++ b/readme.md
@@ -17,6 +17,11 @@ openapi.yml
Rest API accepts xml documents, given querry and processor version to call requested xml engine to perform given
operation and finally returns outcome in response body.
+## Flask Python backend
+
+This is module providing support for processing XMLs using libxml library. It consumes same JSON as Java backend.
+
+
## Mocked services
MockedServices is a tool that allows developer to create, in easy and simple way, http server mocked endpoints for integration tests