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..c652212 --- /dev/null +++ b/Backend-libXML/Parser.py @@ -0,0 +1,69 @@ +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: Message saying, if the validation was successful or not + :rtype: str + """ + xml_schema = etree.XMLSchema(etree.XML(xsd)) + + xml = etree.XML(source) + if xml_schema.validate(xml): + return "XML is valid." + else: + return "XML is NOT valid." + + +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..0869a00 --- /dev/null +++ b/Backend-libXML/main.py @@ -0,0 +1,74 @@ +from flask import Flask +from flask_cors import CORS +from flask import request +from lxml import etree +import json +import time +import Parser + + +app = Flask(__name__) +CORS(app) +cors = CORS(app, resource={ + r"/*":{ + "origins":"*" + } +}) + +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..7c41ff0 --- /dev/null +++ b/Backend-libXML/requirements.txt @@ -0,0 +1,3 @@ +lxml +flask +flask_cors \ No newline at end of file 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": "Hamlet2001-05-041falseMacbeth2000-12-131falseHarry Potter and the Sorcerer's Stone2005-04-292trueThe Long Walk2018-07-014trueMisery2018-01-314trueThink and Grow Rich2004-09-106trueThe Law of Success1982-05-096falsePatriot Games1995-10-215falseThe Sum of All Fears1992-09-195falseThe Alchemist2017-02-203falseHamlet1994-06-011falseMeasure for Measure1990-03-231falseHamlet1989-05-051trueHamlet1999-05-301trueThe Law of Success2004-11-266trueRomeo and Juliet1997-02-081trueThe Alchemist2009-08-213true", + "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": "Hamlet2001-05-041falseMacbeth2000-12-131falseHarry Potter and the Sorcerer's Stone2005-04-292trueThe Long Walk2018-07-014trueMisery2018-01-314trueThink and Grow Rich2004-09-106trueThe Law of Success1982-05-096falsePatriot Games1995-10-215falseThe Sum of All Fears1992-09-195falseThe Alchemist2017-02-203falseHamlet1994-06-011falseMeasure for Measure1990-03-231falseHamlet1989-05-051trueHamlet1999-05-301trueThe Law of Success2004-11-266trueRomeo and Juliet1997-02-081trueThe Alchemist2009-08-213true", + "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": "TestTest3", + "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": "Hamlet2001-05-041falseMacbeth2000-12-131falseHarry Potter and the Sorcerer's Stone2005-04-292trueThe Long Walk2018-07-014trueMisery2018-01-314trueThink and Grow Rich2004-09-106trueThe Law of Success1982-05-096falsePatriot Games1995-10-215falseThe Sum of All Fears1992-09-195falseThe Alchemist2017-02-203falseHamlet1994-06-011falseMeasure for Measure1990-03-231falseHamlet1989-05-051trueHamlet1999-05-301trueThe Law of Success2004-11-266trueRomeo and Juliet1997-02-081trueThe Alchemist2009-08-213true", + "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 f597720..8bedcb9 100644 --- a/Backend/mocked-services/src/main/resources/static/html/mock.html +++ b/Backend/mocked-services/src/main/resources/static/html/mock.html @@ -3,12 +3,12 @@ R11 MockedServices - - + + - + - +
@@ -37,15 +37,15 @@
- - - + +
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 deleted file mode 100644 index b13a6e1..0000000 --- a/Backend/mocked-services/src/main/resources/static/js/dyn_host.js +++ /dev/null @@ -1,11 +0,0 @@ -$(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/Backend/xslt-rest/src/main/java/com/r11/tools/xslt/SparkInitializer.java b/Backend/xslt-rest/src/main/java/com/r11/tools/xslt/SparkInitializer.java index e17ad41..99a6133 100644 --- a/Backend/xslt-rest/src/main/java/com/r11/tools/xslt/SparkInitializer.java +++ b/Backend/xslt-rest/src/main/java/com/r11/tools/xslt/SparkInitializer.java @@ -1,5 +1,6 @@ package com.r11.tools.xslt; +import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.r11.tools.xslt.processors.Saxon; @@ -65,8 +66,15 @@ public class SparkInitializer { Map responseMap = new HashMap<>(); try { requestMap = mapper.readValue(body, Map.class); - } catch (JsonMappingException ex) { - ex.printStackTrace(); + } catch (JsonMappingException | JsonParseException ex) { + LOG.error("Request JSON error. " + ex); + responseMap.put("result", ex.getMessage()); + responseMap.put("processor", "N/A"); + responseMap.put("status", "ERR"); + responseMap.put("time", "N/A"); + resp.status(400); + resp.body(mapper.writeValueAsString(responseMap)); + return resp; } String data = requestMap.get("data"); @@ -103,8 +111,15 @@ public class SparkInitializer { Map responseMap = new HashMap<>(); try { requestMap = mapper.readValue(body, Map.class); - } catch (JsonMappingException ex) { - LOG.error("JSON mapping error. " + ex); + } catch (JsonMappingException | JsonParseException ex) { + LOG.error("Request JSON error. " + ex); + responseMap.put("result", ex.getMessage()); + responseMap.put("processor", "N/A"); + responseMap.put("status", "ERR"); + responseMap.put("time", "N/A"); + resp.status(400); + resp.body(mapper.writeValueAsString(responseMap)); + return resp; } String data = requestMap.get("data"); @@ -158,7 +173,6 @@ public class SparkInitializer { duration = System.currentTimeMillis() - timeStart; LOG.info("Request: " + body + " processed in " + duration + " ms."); responseMap.put("processor", Xalan.getVersion()); - responseMap.put("result", tmp); responseMap.put("time", Long.toString(duration)); resp.body(mapper.writeValueAsString(responseMap)); return resp; @@ -174,17 +188,24 @@ public class SparkInitializer { private static final Route xsltHandler = (Request req, Response resp) -> { String body = req.body(); ObjectMapper mapper = new ObjectMapper(); - Map jsonMap = new HashMap<>(); + Map requestMap = new HashMap<>(); Map responseMap = new HashMap<>(); try { - jsonMap = mapper.readValue(body, Map.class); - } catch (JsonMappingException ex) { - LOG.error("JSON mapping error. " + ex); + requestMap = mapper.readValue(body, Map.class); + } catch (JsonMappingException | JsonParseException ex) { + LOG.error("Request JSON error. " + ex); + responseMap.put("result", ex.getMessage()); + responseMap.put("processor", "N/A"); + responseMap.put("status", "ERR"); + responseMap.put("time", "N/A"); + resp.status(400); + resp.body(mapper.writeValueAsString(responseMap)); + return resp; } - String data = jsonMap.get("data"); - String query = jsonMap.get("process"); - String processor = jsonMap.get("processor"); - String version = jsonMap.get("version"); + String data = requestMap.get("data"); + String query = requestMap.get("process"); + String processor = requestMap.get("processor"); + String version = requestMap.get("version"); if (processor == null) { return "saxon, xalan"; diff --git a/Backend/xslt-rest/src/main/java/com/r11/tools/xslt/processors/Xalan.java b/Backend/xslt-rest/src/main/java/com/r11/tools/xslt/processors/Xalan.java index 42db619..85fb7e7 100644 --- a/Backend/xslt-rest/src/main/java/com/r11/tools/xslt/processors/Xalan.java +++ b/Backend/xslt-rest/src/main/java/com/r11/tools/xslt/processors/Xalan.java @@ -1,8 +1,12 @@ package com.r11.tools.xslt.processors; +import net.sf.saxon.lib.RawResult; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.xpath.XPathAPI; import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.traversal.NodeIterator; import org.xml.sax.InputSource; import javax.xml.XMLConstants; @@ -19,8 +23,7 @@ import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathFactory; -import java.io.StringReader; -import java.io.StringWriter; +import java.io.*; /** * Handler for Xalan engine @@ -53,25 +56,55 @@ public class Xalan { return sw.toString(); } + private static boolean isTextNode(Node n) { + if (n == null) + return false; + short nodeType = n.getNodeType(); + return nodeType == Node.CDATA_SECTION_NODE || nodeType == Node.TEXT_NODE; + } + /** * Process xpath and return either node or wrapped atomic value - * @deprecated - * Xalan needs assumption of the outcome, which is not implemented. Therefore method is deprecated * @param data xml * @param transform xpath * @return xml processed using given xpath * @throws Exception thrown on node building errors or invalid xpath */ - public static String processXPath(String data, String transform) throws Exception{ - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); + public static String processXPath(String data, String transform) throws Exception { - XPath xpath = XPathFactory.newInstance().newXPath(); + // Set up a DOM tree to query. + InputSource in = new InputSource(new StringReader(data)); + DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); + dfactory.setNamespaceAware(true); + Document doc = dfactory.newDocumentBuilder().parse(in); - xpath.setNamespaceContext(new XalanNamespaceResolver(builder.parse(new InputSource(new StringReader(data))), true)); - XPathExpression exp = xpath.compile(transform); - exp.evaluate(new InputSource(new StringReader(data)), XPathConstants.NODESET); - return exp.evaluate(new InputSource(new StringReader(data))); + // Set up an identity transformer to use as serializer. + Transformer serializer = TransformerFactory.newInstance().newTransformer(); + serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + + // Use the simple XPath API to select a nodeIterator. + NodeIterator nl = XPathAPI.selectNodeIterator(doc, transform); + + // Serialize the found nodes to result object. + StringBuilder result = new StringBuilder(); + Node n; + while ((n = nl.nextNode())!= null) { + StringBuilder sb; + if (isTextNode(n)) { + // DOM may have more than one node corresponding to a + // single XPath text node. Coalesce all contiguous text nodes + // at this level + for (Node nn = n.getNextSibling(); isTextNode(nn); nn = nn.getNextSibling()) { + result.append(nn.getNodeValue()); + } + } else { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + serializer.transform(new DOMSource(n), new StreamResult(new OutputStreamWriter(outputStream))); + result.append(outputStream); + } + result.append("\n"); + } + return result.toString(); } /** diff --git a/Frontend/assets/css/mock-service/common.css b/Frontend/assets/css/mock-service/common.css deleted file mode 100644 index 0c7e754..0000000 --- a/Frontend/assets/css/mock-service/common.css +++ /dev/null @@ -1,6 +0,0 @@ -@import url('https://necolas.github.io/normalize.css/8.0.1/normalize.css'); -@import url('r11addons.css'); -@import url('r11tables.css'); -@import url('r11tool.css'); -@import url('r11tooltip.css'); -@import url('r11modal.css'); diff --git a/Frontend/assets/css/mock-service/main.css b/Frontend/assets/css/mock-service/main.css deleted file mode 100644 index 2f8c9ff..0000000 --- a/Frontend/assets/css/mock-service/main.css +++ /dev/null @@ -1,4 +0,0 @@ -.overflowedTableContent { - max-height: 750px; - overflow: scroll; -} \ No newline at end of file diff --git a/Frontend/assets/css/mock-service/r11addons.css b/Frontend/assets/css/mock-service/r11addons.css deleted file mode 100644 index afb4425..0000000 --- a/Frontend/assets/css/mock-service/r11addons.css +++ /dev/null @@ -1,59 +0,0 @@ -.modification-button.btn-tile:hover { - color: #ca1111; -} - -.modification-button.btn-tile { - width: 10%; - margin: 20% 0 0 0; - font-size: 14px; - color: #00000020 -} - -.modification-button.btn-addtile { - font-size: 38px; - color: #00000030; -} - -.modification-button.btn-addtile:hover { - color: #58ac43; -} - -.tile { - width: 100%; - padding-top: 40%; - border: 1px solid gray; - border-radius: 3px; - position: relative; - background: #f0f0f095; - margin-bottom: 10px; - cursor: default; -} - -.tile:hover { - filter: brightness(110%); -} - -.tile.active { - background: #00000070; - color: white; - filter: none; -} - -.tile.active .btn-tile { - opacity: 0; -} - -.tile .content { - position: absolute; - left: 0; - top: 0; - bottom: 0; - right: 0; - padding: 0 2% 0 7%; - display: flex; -} - -.content p { - margin: 0; - padding: 0; -} diff --git a/Frontend/assets/css/mock-service/r11modal.css b/Frontend/assets/css/mock-service/r11modal.css deleted file mode 100644 index 7848a43..0000000 --- a/Frontend/assets/css/mock-service/r11modal.css +++ /dev/null @@ -1,104 +0,0 @@ -#overlay { - position: fixed; - left: 0; - right: 0; - top: 0; - bottom: 0; - opacity: 0; - background: rgba(0, 0 , 0, 0.5); - pointer-events: none; -} - -#overlay.active { - pointer-events: all; - opacity: 1; -} - -.modal { - display: none; - width: 390px; - min-height: 71px; - max-height: 700px; - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - background: white; - padding: 5px; - border: 1px solid #f0f0f0; -} - -.modal.active { - display: block; -} - -.modal div.header { - width: 384px; - height: 24px; - background: #2e3133; - color: white; - font-size: 24px; - font-weight: 700; - padding: 3px; - margin-bottom: 5px; - display: flex; - justify-content: space-between; - align-items: center; -} - -.modal div.header button { - font-size: 100%; - font-family: inherit; - border: 0; - padding: 0; - background: 0; - color: inherit; - cursor: pointer; -} - -.modal div.header button:hover { - color: white; - font-weight: 700; -} - -.modal div.body { - width: 370px; - padding: 10px; - background: #f0f0f0; - color: #2e3133; - min-height: 16px; - text-align: justify; - font-size: 16px; -} - -.modal div.function { - width: 385px; - min-height: 30px; - padding-top: 5px; - display: flex; - justify-content: space-evenly; - background: inherit; -} - -.modal div.function button { - min-height: 22px; - min-width: 34px; - max-width: 74px; - padding: 3px 20px; - outline: none; - border: 1px solid #f0f0f0; - background: rgba(205,205,205,1); - font-size: 16px; - text-align: center; - cursor: pointer; -} - -.modal div.function button:hover { - filter: brightness(110%); -} - -.r-exclamation:before { - content: '!'; - color: #3bc4f1; - font-style: normal; -} diff --git a/Frontend/assets/css/mock-service/r11tables.css b/Frontend/assets/css/mock-service/r11tables.css deleted file mode 100644 index 0a680ab..0000000 --- a/Frontend/assets/css/mock-service/r11tables.css +++ /dev/null @@ -1,71 +0,0 @@ -.table-map { - width: 60%; -} - -.table-map input{ - font-size: 16px; - padding: 7px; - border: 1px solid rgba(145, 146, 146, 0.849); - border-radius: 5px; -} - -.table-map input.key { - background: #f0f0f0; -} - -.modification-button.btn-add { - font-size: 16px; - color: #00000030; - margin: auto 0 auto 0; -} - -.modification-button.btn-add:hover { - color:#58ac43; -} - -.modification-button.btn-hashmap { - font-size: 16px; - color: #00000030; - margin: auto 0 auto 0; -} - -.modification-button.btn-hashmap:hover { - color: #ca1111; -} - -.table-default { - width: 80%; - border-collapse: collapse; - border-spacing: 0; -} - -.table-default tr { - background: #f0f0f02d; -} - -.table-default tr.bottom-border { - border-bottom: 1px solid black; -} - -.table-default th { - background: #ffffff; -} - -.table-default tr.even { - background: #f0f0f0; -} - -.table-doc td, .table-doc th{ - border-spacing: 0px; - padding: 0px 10px; -} - -.table-doc td { - background-color: rgba(155, 165, 160, 0.342); -} - -.table-doc th { - background-color: #3bc4f1; - text-align: left; - color: white; -} \ No newline at end of file diff --git a/Frontend/assets/css/mock-service/r11tool.css b/Frontend/assets/css/mock-service/r11tool.css deleted file mode 100644 index 2243166..0000000 --- a/Frontend/assets/css/mock-service/r11tool.css +++ /dev/null @@ -1,300 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@300;400;700&display=swap'); -.hyperlink, .hyperlink:visited, .hyperlink:active { - color: rgb(47, 125, 146); - cursor: pointer; -} - -.hyperlink:hover { - filter: brightness(120%); -} - -.bordered-field { - border: 2px solid rgba(93, 99, 96, 0.705); - border-radius: 5px; - padding: 8px; - -} - -.bordered-field:focus { - outline: none; - box-shadow: 0 0 5px rgba(81, 203, 238); - border: 2px solid #00000070; -} - -.bordered-field:disabled { - background: #eeeeeed2; -} - -.vertically-resizeable { - resize: vertical; -} - -body { - font-family: 'Nunito', sans-serif; -} - -.container { - display: flex; - justify-content: left; - width: 100%; -} - -.tool { - width: 55%; - display: flex; - justify-content: space-evenly; -} - -.tool.extended { - width: 65%; -} - -.tool .tool-context { - width: 90%; -} - -.tool.extended .tool-context { - width: 75%; -} - -.tool.extended .tool-extention { - width: 20%; - padding-top: 2%; - display: block; -} - -.tool .tool-extention { - display: none; -} - -.tool-extention { - opacity: 0; - pointer-events: none; -} - -.tool-extention.active { - opacity: 100%; - pointer-events: all; -} - -.clickable-text { - padding: 0; - outline: none; - background: none; - border: none; - font-weight: 300; - cursor: pointer; -} - -.clickable-text.highlight:hover { - color: #3bc4f1; -} - -.clickable-text.switch { - font-size: 18px; - font-weight: 700; -} - -.clickable-text.switch span.toggleIndicator:before { - content: '>'; -} - -.clickable-text.switch span.toggleIndicator.active:before { - content: 'v'; -} - -.modification-button { - padding: 0; - outline: none; - background: none; - border: none; - font-weight: 300; -} - -.text-aligned-to-right { - text-align: right; -} - -.centered-vertically { - margin-top: auto; - margin-bottom: auto; -} - -.display-space-between { - width: 100%; - display: flex; - justify-content: space-between; -} - -.display-space-evenly { - display: flex; - justify-content: space-evenly; -} - -.float-left { - display: flex; - justify-content: left; - width: 100%; -} - -.version-span { - font-size: 13px; - font-weight: 400; - color: rgba(85,85,85,0.555); -} - -.block-display { - display: block; -} - -.block-label { - display: block; - margin: 0 0 0 5px; -} - -.tabmenu { - display: flex; - flex-direction: row; - text-align: center; - border-bottom: 1px solid rgba(185, 185, 185, 0.5); -} - -.tabitem { - flex-grow: 1; - cursor: pointer; - padding: 5px 0; -} - -.tabitem:hover { - font-weight: 700; -} - -.tabitem.active { - background: rgba(33, 34, 34, 0.705); - color: white; - font-weight: 700; - cursor:default; - flex-grow: 1; -} - -.big-font { - font-size: 20px; -} - -.action-button.active { - background: #3bc4f1; - border: 1px solid #7ed0eb; - cursor: pointer; -} - -.action-button.active:hover { - filter: brightness(110%); -} - -.action-button { - background: rgba(155, 165, 160, 0.507); - border:1px solid rgba(186, 197, 191, 0.507); - color: white; - padding: 10px 20px; - font-weight: 700; - margin: 3px 0; -} - -.quater-width { - width: 25%; -} - -.half-width { - width: 50%; -} - -.tree-fourth-width { - width: 75%; -} - -.half-width.with-padding { - width: 45%; -} - -.max-width { - width: 100%; -} - -.max-width.with-padding { - width: 94%; -} - -.max-height { - height: 100%; -} - -.height-300 { - height: 300px; -} - -.max-height.with-padding { - height: 90%; -} - -.small-margins { - margin: 3%; -} - -.small-vertical-margin { - margin-top: 10px; - margin-bottom: 10px; -} - -.medium-vertical-margin { - margin-top: 30px; - margin-bottom: 30px; -} - -.large-vertical-margin { - margin-top: 50px; - margin-bottom: 50px; -} - -.textarea-300 { - height: 300px; -} - -.centered-content { - display: flex; - justify-content: center; -} - - -.tabcontent { - display: none; -} - -.tabcontent.active { - display: flex; - justify-content: center; -} - -.hiddable { - display: none; -} - -.hiddable.active { - display: inherit; -} - -/* In case of collision with classes that use 'active' */ -.hidden { - display: none; -} - -/* TODO: Add proper class */ -/* textarea { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} */ - -/* TODO: Add proper class */ -/* code{ - line-height: 150%; -} */ \ No newline at end of file diff --git a/Frontend/assets/css/mock-service/r11tooltip.css b/Frontend/assets/css/mock-service/r11tooltip.css deleted file mode 100644 index 34fcbfb..0000000 --- a/Frontend/assets/css/mock-service/r11tooltip.css +++ /dev/null @@ -1,77 +0,0 @@ -.tooltip-window { - position: fixed; - right: 0; - filter: drop-shadow(-2px 0px 2px darkgray); - background: #e8f3f7; - padding: 15px 30px; - font-family: 'Nunito', sans-serif; - width: 40%; - height: 100%; - overflow: scroll; -} - -.tooltip-window.lite { - width: 30%; -} - -.tip { - display: none; -} - -.tip.active { - display: block; -} - -/* TODO: Remove !important. It's bad practice and it can cause errors in future */ -.section-button { - width: 100%; - padding: 15px 0; - font-size: 18px; - background: #b4b4b4c5; - cursor: pointer; - border-bottom: darkgray 2px solid !important; -} - -.section-button:hover { - backdrop-filter: brightness(110%); -} - -.section-button .active { - background: #00000030; -} - -.List .collapsibleContent { - border-left: #bdc5c9 2px solid; - overflow: hidden; - background: #ffffff50; -} - -/* TODO: .section class is to generic. It should be renamed */ -.section{ - padding: 10px 0px 20px 0px ; -} - -/* TODO: content subclass already in use. Creating content class overrides the subclass. -Make .content a subclass of .content */ -/* .content { - padding: 0px 15px 0px 15px ; - text-align: justify; - overflow: hidden; - transition: max-height .2s ease-out; - max-height: 0px; - border-left: #c0c2c3 2px solid; - -} */ - -.collapsibleMini::before{ - content: "►"; -} - -.collapsibleMini.active::before{ - content: "▼"; -} - -/* TODO: Add proper class */ -/* button:hover{ - filter: brightness(110%); -} */ \ No newline at end of file diff --git a/Frontend/assets/scripts/tools/scripts.js b/Frontend/assets/scripts/tools/scripts.js index 23818b3..085cd1a 100644 --- a/Frontend/assets/scripts/tools/scripts.js +++ b/Frontend/assets/scripts/tools/scripts.js @@ -105,8 +105,11 @@ function performRequest(text, checkXML, checkTransform){ //Form REST request, send, receive and display in resultArea async function restRequest(text) { const escapeChar = "specialEscapeChar"; - // const addr = "http://localhost:8081/" + text; - const addr = window.location.protocol + "//" + window.location.hostname + ":8081/" + text; + var port = ":8081/" + if (getProcessor() == "libxml") { + port = ":8082/" + } + const addr = window.location.protocol + "//" + window.location.hostname + port + text; var xmlData = document.getElementById("xmlArea").value.trim(); var transformData = document.getElementById("transformArea").value.trim(); diff --git a/Frontend/tools/xpath.html b/Frontend/tools/xpath.html index 3d0a6b3..c7ed0a9 100644 --- a/Frontend/tools/xpath.html +++ b/Frontend/tools/xpath.html @@ -24,13 +24,15 @@

diff --git a/Frontend/tools/xslt.html b/Frontend/tools/xslt.html index cc77f34..131fd3a 100644 --- a/Frontend/tools/xslt.html +++ b/Frontend/tools/xslt.html @@ -19,6 +19,7 @@ procInfo

@@ -1130,7 +1131,7 @@ console.log("processTooltip"); - if (getProcInfo() == "xalan") { + if (getProcInfo() == "xalan" || getProcInfo() == "libxml") { document.getElementById("tooltipFunctionInfo").innerText = "XSLT 1.0 functions"; document.getElementById("processorTooltipInfo").innerText = "Supports XSLT 1.0"; hideList(document.getElementsByName("collapse30")); 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