1 Commits

Author SHA1 Message Date
b52343b3f8 Rearrangement of project structure 2021-04-29 10:53:27 +02:00
32 changed files with 42 additions and 475 deletions

View File

@@ -1,9 +0,0 @@
target/
nbactions.xml
.idea/
.settings/
.classpath
.settings
.project
*.iml
.vscode

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4" />

View File

@@ -1,15 +0,0 @@
package r11.mltx.restxslt;
/**
* Application initializer
* @author Wojciech Czop
*/
public class Main {
/**
* Initializes the application
* @param args
*/
public static void main(String[] args) {
SparkInitializer.run();
}
}

View File

@@ -1,279 +0,0 @@
swagger: "2.0"
info:
description: "This is a simple API allowing you to perform XSLT and XPath operations <br>
Currently we support Xalan and Saxon (libxml2 is in progress) for XSLT and Saxon for XPath"
version: "0.3"
title: "XML Tools API"
host: "gordon.zipper.release11.com:8081"
schemes:
- http
tags:
- name: "XPath"
description: "XPath processing API"
- name: "XSLT"
description: "XSLT processing API"
- name: "XSD"
description: "XSD verification API"
paths:
/xpathpost:
post:
tags:
- "XPath"
summary: "Perform XPath transform on XML file"
description: ""
operationId: "xpath"
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- in: "body"
name: "request"
description: "A transform that is to be performed"
required: true
schema:
$ref: "#/definitions/RequestXPath"
responses:
"200":
description: "successful operation"
schema:
type: "array"
items:
$ref: "#/definitions/Response"
"400":
description: "Invalid status value"
schema:
type: "array"
items:
$ref: "#/definitions/ResponseError"
/xsltpost:
post:
tags:
- "XSLT"
summary: "Perform XSLT transform on XML file"
description: ""
operationId: "xslt"
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- in: "body"
name: "request"
description: "A transform that is to be performed"
required: true
schema:
$ref: "#/definitions/RequestXSLT"
responses:
"200":
description: "successful operation"
schema:
type: "array"
items:
$ref: "#/definitions/Response"
"400":
description: "Invalid status value"
schema:
type: "array"
items:
$ref: "#/definitions/ResponseError"
/xsdpost:
post:
tags:
- "XSD"
summary: "Verify XML file using XSD"
description: ""
operationId: "xsd"
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- in: "body"
name: "request"
description: "A XML that is to be verified"
required: true
schema:
$ref: "#/definitions/RequestXSD"
responses:
"200":
description: "successful operation"
schema:
type: "array"
items:
$ref: "#/definitions/XSDResponse"
"400":
description: "Invalid status value"
schema:
type: "array"
items:
$ref: "#/definitions/XSDError"
definitions:
RequestXPath:
type: "object"
properties:
data:
type: "string"
example: "<values>
<value>Test1</value>
<value>Test3</value>
</values>"
description: "The XML data to be processed"
process:
type: "string"
example: "count(//value)"
description: "XPath tranform to be executed"
processor:
type: "string"
enum:
- "saxon"
- "xalan"
version:
type: "string"
enum:
- "2.0"
- "3.0"
- "3.1"
RequestXSLT:
type: "object"
properties:
data:
type: "string"
example: "<values>
<value>Test1</value>
<value>Test3</value>
</values>"
description: "The XML data to be processed"
process:
type: "string"
example: "count(//value)"
description: "XSLT tranform to be executed"
processor:
type: "string"
enum:
- "saxon"
- "xalan"
version:
type: "string"
enum:
- "2.0"
- "3.0"
- "3.1"
RequestXSD:
type: "object"
properties:
data:
type: "string"
example: "<shiporder orderid=\"889923\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">
<shipto>
<name>Ola Nordmann</name>
<address>Langgt 23</address>
<city>4000 Stavanger</city>
<country>Norway</country>
</shipto>
</shiporder>"
description: "The XML data to be processed"
process:
type: "string"
example: "<shiporder orderid=\"889923\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">
<shipto>
<name>Ola Nordmann</name>
<address>Langgt 23</address>
<city>4000 Stavanger</city>
<country>Norway</country>
</shipto>
</shiporder>"
description: "XSD to perform verification with"
processor:
type: "string"
enum:
- "saxon"
- "xalan"
version:
type: "string"
enum:
- "2.0"
- "3.0"
- "3.1"
Response:
type: "object"
properties:
result:
type: "string"
example: "4"
description: "Result of performing transformation on provided XML"
time:
type: "string"
example: "320"
description: "Computation time in milliseconds"
processor:
type: "string"
enum:
- "Saxon 10.3 2.0 over s9api"
- "Xalan Java 2.7.2"
status:
type: "string"
enum:
- "OK"
ResponseError:
type: "object"
properties:
result:
type: "string"
example: "Concatenation operator ('||') requires XPath 3.0 to be enabled"
description: "Error from XPath processor"
time:
type: "string"
example: "40"
description: "Computation time in milliseconds"
processor:
type: "string"
enum:
- "Saxon 10.3 2.0 over s9api"
- "Xalan Java 2.7.2"
status:
type: "string"
enum:
- "ERR"
XSDResponse:
type: "object"
properties:
result:
type: "string"
example: "XML file is valid"
description: "Validation result"
time:
type: "string"
example: "7"
description: "Computation time in milliseconds"
processor:
type: "string"
enum:
- "Xalan Java 2.7.2"
status:
type: "string"
enum:
- "OK"
XSDError:
type: "object"
properties:
result:
type: "string"
example: "The end-tag for element type \"xs:complexType\" must end with a '>' delimiter."
description: "Validation result"
time:
type: "string"
example: "7"
description: "Computation time in milliseconds"
processor:
type: "string"
enum:
- "Xalan Java 2.7.2"
status:
type: "string"
enum:
- "ERR"
externalDocs:
description: "Find out more about Swagger"
url: "http://swagger.io"

View File

@@ -24,7 +24,7 @@
<!-- <manifest>-->
<!-- <addClasspath>true</addClasspath>-->
<!-- <classpathPrefix>lib/</classpathPrefix>-->
<!-- <mainClass>r11.mltx.restxslt.Main</mainClass>-->
<!-- <mainClass>Main</mainClass>-->
<!-- </manifest>-->
<!-- </archive>-->
<!-- </configuration>-->
@@ -48,7 +48,7 @@
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>r11.mltx.restxslt.Main</mainClass>
<mainClass>Main</mainClass>
</manifest>
</archive>
<descriptorRefs>

View File

@@ -1,41 +0,0 @@
# XML Tools
Content of this project is a service hosting tools for xml documents including xslt transformer,
xpath selector and xsd validator.
## About project
Service is split into two microservices one containing JavaSpark web application and second hosting
static documents.
## JavaSpark backend
Backend is hosted by default on port 8081. Rest api documentation is contained in OpenApi document
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.
## Frontend
All the static files are available by default on port 8086 and are located within folder.
To preview given document user is required to post GET request to following path:
```aidl
/Frontend/{document name}
```
Documents are hosted by docker container running on ngix image and to modify container content
one must modify Dockerfile located in Frontend folder. Files published must be located in ngix directory
within created container.
## How to run
### Localy
In order to run application use
```aidl
docker-compose up --build -d
```
Which will launch service on localhost.
### Remote
To launch service on remote host, exchange ssh keys with destination server and declare docker context ex. DEV.
Then use following command
```aidl
docker-compose up --context DEV --build -d
```

View File

@@ -1,24 +1,14 @@
package r11.mltx.restxslt;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import r11.mltx.restxslt.processors.Saxon;
import r11.mltx.restxslt.processors.Xalan;
import processors.Saxon;
import processors.Xalan;
import spark.*;
import java.util.HashMap;
import java.util.Map;
/**
* Class contains spark configuration and method initializing spark framework
* @author Wojciech Czop
*/
public class SparkInitializer {
/**
* Initializes spark framework
*/
public static void run(){
// TODO: Port value as property
public class Main {
public static void main(String[] args) {
Spark.port(8081);
Spark.after((Filter) (request, response) -> {
@@ -35,11 +25,9 @@ public class SparkInitializer {
System.out.println("Server is online");
}
/**
* Handler that returns processor version
*/
private static Route procinfoHandler = (Request req, Response resp) -> {
static Route procinfoHandler = (Request req, Response resp) -> {
try {
// req.session().id
resp.header("processor", "Saxon " + Saxon.getVersion() + " over s9api");
return Saxon.getVersion();
} catch (Exception ex) {
@@ -47,11 +35,7 @@ public class SparkInitializer {
}
};
/**
* Handler that returns info if document is valid
* Also provides info about request time and processor
*/
private static Route xsdHandler = (Request req, Response resp) -> {
static Route xsdHandler = (Request req, Response resp) -> {
String body = req.body();
System.out.println("Request: " + body);
ObjectMapper mapper = new ObjectMapper();
@@ -88,10 +72,7 @@ public class SparkInitializer {
return resp;
};
/**
* Handler that returns output of xpath query and processor data
*/
private static Route xpathHandler = (Request req, Response resp) -> {
static Route xpathHandler = (Request req, Response resp) -> {
String body = req.body();
System.out.println("Request: " + body);
@@ -167,10 +148,7 @@ public class SparkInitializer {
}
};
/**
* Handler that returns outcome of xslt transformation and processor data
*/
private static Route xsltHandler = (Request req, Response resp) -> {
static Route xsltHandler = (Request req, Response resp) -> {
String body = req.body();
ObjectMapper mapper = new ObjectMapper();
Map<String, String> jsonMap = null;
@@ -195,6 +173,7 @@ public class SparkInitializer {
long duration = 0;
switch (processor) {
case "saxon":
// resp.header("processor", "Saxon " + Saxon.getVersion());
timeStart = System.currentTimeMillis();
try {
tmp = Saxon.processXSLT(data, query);
@@ -236,5 +215,6 @@ public class SparkInitializer {
} catch (Exception ex) {
return ex.getMessage();
}
};
}

View File

@@ -1,4 +1,4 @@
package r11.mltx.restxslt.processors;
package processors;
import net.sf.saxon.om.NamespaceBinding;
import net.sf.saxon.om.NamespaceMap;
@@ -7,50 +7,29 @@ import net.sf.saxon.s9api.XdmNode;
import java.util.Iterator;
/**
* Handler for saxon namespace scan engine.
* All found namespaces are stored within {@link #namespaceMap}
* @author Wojciech Czop
*/
public class NewNamespaceResolver {
private NamespaceMap namespaceMap;
/**
* Initializes {@link #namespaceMap} with namespace values
* @param doc dom structure object
* @return map of namespaces
*/
public NamespaceMap process(XdmNode doc) {
namespaceMap = NamespaceMap.emptyMap();
Iterator<XdmNode> it = doc.children().iterator();
// TODO: remove
while (it.hasNext()) {
XdmNode tmp = it.next();
extractNamespace(tmp);
}
// end
return namespaceMap;
}
/**
* Iterates through {@link #namespaceMap} and declares namespaces in {@link XPathCompiler}
* @param compiler compiler used to compile xpath statements
*/
public void exportNamespaces(XPathCompiler compiler){
Iterator<NamespaceBinding> it = namespaceMap.iterator();
// TODO: remove
while(it.hasNext()){
System.out.println(it.next());
}
// end
namespaceMap.forEach(namespaceBinding -> compiler.declareNamespace(namespaceBinding.getPrefix(), namespaceBinding.getURI()));
}
/**
* Uses recurrency to dive deep dom structure and appends {@link #namespaceMap} with every found namespace
* @param node dom structure object
*/
private void extractNamespace(XdmNode node) {
NamespaceMap tmp;
if ((tmp = node.getUnderlyingNode().getAllNamespaces()) != null) {
@@ -61,7 +40,6 @@ public class NewNamespaceResolver {
Iterator<XdmNode> it = node.children().iterator();
while (it.hasNext()) {
XdmNode rNode = it.next();
// TODO: remove
if(rNode.getUnderlyingNode().getPrefix().isEmpty() && !rNode.getParent().getUnderlyingNode().getPrefix().isEmpty()){
System.out.println("prefix missing, parent has "+rNode.getParent().getUnderlyingNode().getPrefix() + ", but child has none");
@@ -69,7 +47,6 @@ public class NewNamespaceResolver {
NamespaceMap nsTMP= rNode.getUnderlyingNode().getAllNamespaces();
System.out.println();
}
// end
extractNamespace(rNode);
}
}

View File

@@ -1,4 +1,4 @@
package r11.mltx.restxslt.processors;
package processors;
import net.sf.saxon.om.NamespaceMap;
import net.sf.saxon.s9api.*;
@@ -6,19 +6,7 @@ import javax.xml.transform.stream.StreamSource;
import java.io.StringReader;
import java.io.StringWriter;
/**
* Handler for Saxon engine
* @author Wojciech Czop
*/
public class Saxon {
/**
* Transforms string containing xml document via xslt
* @param data xml to be transformed
* @param transform xslt
* @return transformed xml
* @throws SaxonApiException
*/
public static String processXSLT(String data, String transform) throws SaxonApiException {
Processor processor = new Processor(false);
XsltCompiler compiler = processor.newXsltCompiler();
@@ -33,20 +21,14 @@ public class Saxon {
return sw.toString();
}
/**
* Process xpath and return either node or wrapped atomic value
* @param data xml to be querried
* @param query xpath queryy
* @param version processor version
* @return string xml representation of the node
* @throws Exception
*/
public static String processXPath(String data, String query, String version) throws Exception {
Processor p = new Processor(false);
XPathCompiler compiler = p.newXPathCompiler();
DocumentBuilder builder = p.newDocumentBuilder();
XdmNode doc = builder.build(new StreamSource(new StringReader(data)));
// System.out.println(version);
compiler.setLanguageVersion(version);
NewNamespaceResolver resolver = new NewNamespaceResolver();
@@ -65,10 +47,6 @@ public class Saxon {
}
/**
* Returns version of the processor
* @return version of the processor
*/
public static String getVersion() {
return new Processor(false).getSaxonProductVersion();
}

View File

@@ -1,9 +1,10 @@
package r11.mltx.restxslt.processors;
package processors;
import net.sf.saxon.s9api.SaxonApiException;
import org.apache.xpath.domapi.XPathEvaluatorImpl;
import org.w3c.dom.Document;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
@@ -17,33 +18,29 @@ import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* Handler for Xalan engine
* @author Wojciech Czop
*/
public class Xalan {
/**
* Transforms string containing xml document via xslt
* @param data xml to be transformed
* @param transform xslt
* @return transformed xml
* @throws Exception
*/
public static String processXSLT(String data, String transform) throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource(new StringReader(data)));
StreamSource stylesource = new StreamSource(new StringReader(transform));
Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
Source source = new DOMSource(document);
StringWriter sw = new StringWriter();
Result outputTarget = new StreamResult(sw);
@@ -52,15 +49,6 @@ public class Xalan {
return sw.toString();
}
/**
* 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
* @param transform
* @return
* @throws Exception
*/
public static String processXPath(String data, String transform) throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
@@ -73,30 +61,31 @@ public class Xalan {
String result = exp.evaluate(new InputSource(new StringReader(data)));
return result;
}
/**
* Returns version of the processor
* @return version of the processor
*/
public static String getVersion(){
return org.apache.xalan.Version.getVersion();
}
/**
* Validates string representation of the xml document against xsd schema
* @param data xml document
* @param xsd xsd schema
* @return statement of validity
* @throws Exception
*/
public static String validate(String data, String xsd) throws Exception{
Source dataSource = new StreamSource(new StringReader(data));
Source xsdSource = new StreamSource(new StringReader(xsd));
SchemaFactory schemaFactory = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
// try {
Schema schema = schemaFactory.newSchema(xsdSource);
Validator validator = schema.newValidator();
validator.validate(dataSource);
// System.out.println(dataSource.getSystemId() + " is valid");
return "XML file is valid";
// } catch (SAXException e) {
// System.out.println("Invalid: "+e.getMessage());
// return "XML file is NOT valid: " + e.getMessage();
//// System.out.println(dataSource.getSystemId() + " is NOT valid reason:" + e);
// } catch (IOException e) {
// return "IO error: "+e.getMessage();
// }
}
}

View File

@@ -1,4 +1,4 @@
package r11.mltx.restxslt.processors;
package processors;
import org.w3c.dom.*;
@@ -8,12 +8,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Contains methods that scan document for namespaces and store them in map objects.
* @deprecated
* Class no longer in use. It has been replaced by {@link NewNamespaceResolver}
* @author Wojciech Czop
*/
public class XalanNamespaceResolver implements NamespaceContext {
private static final String DEFAULT_NS = "DEFAULT";
private Map<String, String> prefix2Uri = new HashMap<String, String>();
@@ -90,11 +84,6 @@ public class XalanNamespaceResolver implements NamespaceContext {
}
/**
* Stores namespace prefix ass well as its uri in map
* @param prefix
* @param uri
*/
private void putInCache(String prefix, String uri) {
prefix2Uri.put(prefix, uri);
uri2Prefix.put(uri, prefix);

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB