diff --git a/README.md b/README.md index a2917a1..aa6b074 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,15 @@ Usage ----- The processor can be run using Maven, so make sure you have installed it first: http://maven.apache.org/download.cgi You can run a mapping process by executing the following command. + +Master branch: mvn exec:java -Dexec.args=" []" +HTML branch: + + mvn exec:java -Dexec.args=" []" + With = Java properties file containing key-value pairs which configure the data sources used in the mapping file. diff --git a/pom.xml b/pom.xml index f9c995f..b6e3eb2 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 0.1 jar - RML Processor5 + RML Processor6 http://maven.apache.org @@ -103,6 +103,12 @@ 2.0.1 jar + + org.jodd + jodd-lagarto + 3.5 + jar + diff --git a/src/main/java/be/ugent/mmlab/rml/core/SimpleReferencePerformer.java b/src/main/java/be/ugent/mmlab/rml/core/SimpleReferencePerformer.java index c435bac..c8e84a4 100644 --- a/src/main/java/be/ugent/mmlab/rml/core/SimpleReferencePerformer.java +++ b/src/main/java/be/ugent/mmlab/rml/core/SimpleReferencePerformer.java @@ -2,14 +2,12 @@ import be.ugent.mmlab.rml.model.TriplesMap; import be.ugent.mmlab.rml.processor.RMLProcessor; -import java.util.ArrayList; import java.util.List; import net.antidot.semantic.rdf.model.impl.sesame.SesameDataSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openrdf.model.Resource; import org.openrdf.model.URI; -import org.openrdf.model.Value; import org.openrdf.model.impl.URIImpl; /** @@ -35,11 +33,14 @@ public void perform(Object node, SesameDataSet dataset, TriplesMap map) { log.debug("[SimpleReferencePerformer:object] " + "values " + values); for(String value : values){ - Resource object = new URIImpl(value); + Resource object; + if(value.startsWith("http") || value.startsWith("ftp")){ + object = new URIImpl(value); dataset.add(subject, predicate, object); log.debug("[SimpleReferencePerformer:addTriples] Subject " + subject + " Predicate " + predicate + "Object " + object.toString()); + } } diff --git a/src/main/java/be/ugent/mmlab/rml/processor/AbstractRMLProcessor.java b/src/main/java/be/ugent/mmlab/rml/processor/AbstractRMLProcessor.java index 5882338..f173203 100644 --- a/src/main/java/be/ugent/mmlab/rml/processor/AbstractRMLProcessor.java +++ b/src/main/java/be/ugent/mmlab/rml/processor/AbstractRMLProcessor.java @@ -25,6 +25,7 @@ import java.util.HashMap; import java.util.List; import java.util.Set; +import java.util.regex.Pattern; import net.antidot.semantic.rdf.model.impl.sesame.SesameDataSet; import net.antidot.semantic.rdf.rdb2rdf.r2rml.core.R2RMLEngine; import net.antidot.semantic.rdf.rdb2rdf.r2rml.tools.R2RMLToolkit; @@ -93,10 +94,12 @@ public Resource processSubjectMap(SesameDataSet dataset, SubjectMap subjectMap, if (value == null) { return null; } + + if(value.startsWith("http") || value.startsWith("ftp")) + return new URIImpl(value); + else + return null; - Resource subject = new URIImpl(value); - - return subject; } public void processSubjectTypeMap(SesameDataSet dataset, Resource subject, SubjectMap subjectMap, Object node) { @@ -104,7 +107,8 @@ public void processSubjectTypeMap(SesameDataSet dataset, Resource subject, Subje //Add the type triples Set classIRIs = subjectMap.getClassIRIs(); for (org.openrdf.model.URI classIRI : classIRIs) { - dataset.add(subject, RDF.TYPE, classIRI); + if(subject != null) + dataset.add(subject, RDF.TYPE, classIRI); } } @@ -142,11 +146,9 @@ public List processTermMap(TermMap map, Object node) { if (value.size() < (i + 1)) { value.add(template); } - String replacement = replacements.get(i).trim(); - //if (replacement == null || replacement.isEmpty()) { - if (replacement == null) { + if (replacement == null && !replacement.equals("")) { //if the replacement value is null or empty, the reulting uri would be invalid, skip this. //The placeholders remain which removes them in the end. continue; @@ -154,10 +156,6 @@ public List processTermMap(TermMap map, Object node) { String temp = value.get(i).trim(); - if (expression.contains("[")) { - expression = expression.replaceAll("\\[", "").replaceAll("\\]", ""); - temp = temp.replaceAll("\\[", "").replaceAll("\\]", ""); - } //JSONPath expression cause problems when replacing, remove the $ first if (expression.contains("$")) { expression = expression.replaceAll("\\$", ""); @@ -165,8 +163,10 @@ public List processTermMap(TermMap map, Object node) { } try { - //Use encoding UTF-8 explicit URL encode; other one is deprecated - temp = temp.replaceAll("\\{" + expression + "\\}", URLEncoder.encode(replacement,"UTF-8")); + //Use encoding UTF-8 explicit URL encode; other one is deprecated + //temp.replaceAll(expression, "body div.CEURTOC h2+ul li a&([\\\\w\\\\d]*)#$1"); + temp = temp.replaceAll("\\{" + Pattern.quote(expression) + "\\}", ((replacement.startsWith("http")||replacement.startsWith("ftp")) ? replacement.toString() : URLEncoder.encode(replacement,"UTF-8"))); + } catch (UnsupportedEncodingException ex) { log.error(ex); } @@ -174,7 +174,7 @@ public List processTermMap(TermMap map, Object node) { value.set(i, temp); } } - + //Check if there are any placeholders left in the templates and remove uris that are not List validValues = new ArrayList(); for (String uri : value){ @@ -182,7 +182,6 @@ public List processTermMap(TermMap map, Object node) { validValues.add(uri); } } - return validValues; default: @@ -220,7 +219,7 @@ public void processPredicateObjectMap(SesameDataSet dataset, Resource subject, P //Create the processor based on the parent triples map to perform the join RMLProcessorFactory factory = new ConcreteRMLProcessorFactory(); QLTerm queryLanguage = parentTriplesMap.getLogicalSource().getQueryLanguage(); - String fileName = null; + String fileName; File file = new File(parentTriplesMap.getLogicalSource().getIdentifier()); if(!file.exists()) fileName = getClass().getResource(parentTriplesMap.getLogicalSource().getIdentifier()).getFile(); diff --git a/src/main/java/be/ugent/mmlab/rml/processor/concrete/CSS3Extractor.java b/src/main/java/be/ugent/mmlab/rml/processor/concrete/CSS3Extractor.java new file mode 100644 index 0000000..e4ffc8e --- /dev/null +++ b/src/main/java/be/ugent/mmlab/rml/processor/concrete/CSS3Extractor.java @@ -0,0 +1,233 @@ +package be.ugent.mmlab.rml.processor.concrete; + +import be.ugent.mmlab.rml.core.RMLMappingFactory; +import be.ugent.mmlab.rml.core.RMLPerformer; +import be.ugent.mmlab.rml.model.TriplesMap; +import be.ugent.mmlab.rml.processor.AbstractRMLProcessor; +import java.io.File; +import java.io.IOException; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import jodd.io.FileUtil; +import net.antidot.semantic.rdf.model.impl.sesame.SesameDataSet; +import jodd.jerry.Jerry; +import jodd.lagarto.dom.Node; +import jodd.lagarto.dom.NodeSelector; +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * + * @author andimou + */ +public class CSS3Extractor extends AbstractRMLProcessor{ + + private static Log log = LogFactory.getLog(RMLMappingFactory.class); + private int enumerator; + + @Override + public void execute(SesameDataSet dataset, TriplesMap map, RMLPerformer performer, String fileName) { + //this should not be needed to be defined within the extractor + String reference = getReference(map.getLogicalSource()); + // more configuration... + Jerry doc = null; + File file = new File(fileName); + try { + doc = Jerry.jerry(FileUtil.readString(file)); + } catch (IOException ex) { + Logger.getLogger(CSS3Extractor.class.getName()).log(Level.SEVERE, null, ex); + } + NodeSelector nodeSelector = null; + nodeSelector = new NodeSelector(doc.get(0)); + + List selectedNodes = nodeSelector.select(reference); + for (int i = 0; i < selectedNodes.size(); i++) { + performer.perform(selectedNodes.get(i).getHtml(), dataset, map); + } + + } + + @Override + public void execute_node(SesameDataSet dataset, TriplesMap map, TriplesMap parentTriplesMap, RMLPerformer performer, Object node) { + int end = map.getLogicalSource().getReference().length(); + String expression = parentTriplesMap.getLogicalSource().getReference().toString().substring(end); + if(expression.startsWith("+")) + expression = expression.substring(1); + + Jerry doc = Jerry.jerry(node.toString()); + NodeSelector nodeSelector = new NodeSelector(doc.get(0)); + + List selectedNodes = nodeSelector.select(expression.trim()); + for(Node selectNode : selectedNodes) + performer.perform(selectNode.getHtml(), dataset, parentTriplesMap); + } + + @Override + + public List extractValueFromNode(Object node, String expression) { + Jerry doc = Jerry.jerry(node.toString()); + List list = new ArrayList(); + String replacement = null; + + String months[] = {"January", "February", "March", "April", + "May", "June", "July", "August", "September", + "October", "November", "December"}; + String shortMonths[] = {"Jan", "Feb", "Mar", "Apr", + "May", "June", "July", "Aug", "Sep", + "Oct", "Nov", "Dec"}; + + if(expression.equals("#")){ + list.add(Integer.toString(enumerator++)); + return list; + } + + if(expression.contains("&")){ + String[] valueList = null; + String regex = expression.split("&")[1]; + expression = expression.split("&")[0]; + + if(regex.startsWith("deduct:")){ + regex = regex.split("deduct:")[1]; + expression = expression.split("\\{")[0]; + String value = StringEscapeUtils.unescapeHtml(doc.$(expression).text().trim().replaceAll("[\\t\\n\\r\\s]{2,}", " ")); + if(!value.isEmpty()){ + if(value.contains("--")) + valueList = value.split("--"); + else + valueList = value.split("-"); + + if(valueList.length>1){ + int val = Integer.parseInt(valueList[1]) - Integer.parseInt(valueList[0]); + + list.add(StringEscapeUtils.unescapeHtml(String.valueOf(val))); + } + else + { + valueList[0] = String.valueOf(1); + list.add(StringEscapeUtils.unescapeHtml(String.valueOf(valueList[0]))); + } + + } + return list; + } + + if(regex.contains("#")){ + replacement = regex.split("#")[1]; + regex = regex.split("#")[0]; + } + + if(regex.contains("href")){ + Node doc2 = doc.get(0); + NodeSelector nodeSelector = new NodeSelector(doc2); + List selectedNodes = nodeSelector.select(expression); + for(Node snode:selectedNodes) + list.add(StringEscapeUtils.unescapeHtml(snode.getAttribute("href").toString().replaceAll(regex, replacement).trim().replaceAll("[\\t\\n\\r\\s]{2,}", " "))); + } + else + { + String value = StringEscapeUtils.unescapeHtml(doc.$(expression).text().trim().replaceAll("[\\t\\n\\r\\s]{2,}", " ")); + if(replacement == null) { + + Node doc2 = doc.get(0); + NodeSelector nodeSelector = new NodeSelector(doc2); + List selectedNodes = nodeSelector.select(expression); + for(Node snode:selectedNodes){ + if(snode.getInnerHtml().toString() != null && !snode.getInnerHtml().toString().equals("")){ + if(!snode.getInnerHtml().toString().trim().replaceAll("[\\t\\n\\r\\s]{2,}", " ").equals("")) + list.add(StringEscapeUtils.unescapeHtml(snode.getInnerHtml().toString().trim().replaceAll("[\\t\\n\\r\\s]{2,}", " "))); + } + } + Pattern pattern = Pattern.compile(expression); + Matcher matcher = pattern.matcher(value); + if(matcher.find()){ + if(!matcher.replaceAll(replacement).equals("") && !matcher.replaceAll(replacement).equals(" ")) + list.add(StringEscapeUtils.unescapeHtml(matcher.group())); + } + else + list.add(StringEscapeUtils.unescapeHtml(value)); + } + else{ + DecimalFormat formatter = new DecimalFormat("00"); + Pattern replace = Pattern.compile(regex); + Matcher matcher = replace.matcher(value); + if(matcher.find()){ + if(!matcher.replaceAll(replacement).equals("") && !matcher.replaceAll(replacement).equals(" ")){ + String[] values = null; + if(matcher.replaceAll(replacement).matches("\\d{1}")){ + int newInt = Integer.parseInt(matcher.replaceAll(replacement)); + list.add(formatter.format(newInt).toString().trim()); + } + + for(int i=0; i<11; i++) + if( matcher.replaceAll(replacement).toString().contains(months[i])) + list.add(String.valueOf(matcher.replaceAll(replacement).replace(months[i], formatter.format(i+1)))); + + for(int i=0; i<11; i++) + if( matcher.replaceAll(replacement).toString().contains(shortMonths[i])) + list.add(String.valueOf(matcher.replaceAll(replacement).replace(shortMonths[i], formatter.format(i+1)))); + + if (replace.toString().contains("Edited by:") || replace.toString().contains("CEURAUTHORS")){ + values = matcher.replaceAll(replacement).split(","); + for(String val:values) + list.add(StringEscapeUtils.unescapeHtml(val)); + } + else + if(!matcher.replaceAll(replacement).equals("")) + list.add(StringEscapeUtils.unescapeHtml(matcher.replaceAll(replacement))); + } + } + } + } + } + else{ + Node doc2 = doc.get(0); + NodeSelector nodeSelector = new NodeSelector(doc2); + List selectedNodes = nodeSelector.select(expression); + for(Node snode:selectedNodes){ + if(snode.getInnerHtml().toString() != null && !snode.getInnerHtml().toString().trim().replaceAll("[\\t\\n\\r\\s]{2,}", " ").equals("")){ + String finVal; + if (expression.contains("CEURAUTHORS")){ + String[] values = snode.getInnerHtml().toString().trim().replaceAll("[\\t\\n\\r\\s]{2,}", " ").split(","); + for(String val:values) + list.add(StringEscapeUtils.unescapeHtml(val)); + } + else{ + finVal = checkforDate(StringEscapeUtils.unescapeHtml(snode.getInnerHtml().toString().trim().replaceAll("[\\t\\n\\r\\s]{2,}", " "))); + if(!finVal.equals("")) + list.add(finVal); + } + } + } + } + return list; + } + + private String checkforDate(String value){ + String months[] = {"January", "February", "March", "April", + "May", "June", "July", "August", "September", + "October", "November", "December"}; + String shortMonths[] = {"Jan", "Feb", "Mar", "Apr", + "May", "June", "July", "Aug", "Sep", + "Oct", "Nov", "Dec"}; + + DecimalFormat formatter = new DecimalFormat("00"); + + for(int i=0; i<11; i++) + if( value.contains(months[i])) + value = String.valueOf(formatter.format(i+1)); + + for(int i=0; i<11; i++) + if( value.contains(shortMonths[i]) ) + value = String.valueOf(formatter.format(i+1)); + + + return value; + } +} diff --git a/src/main/java/be/ugent/mmlab/rml/processor/concrete/CSVProcessor.java b/src/main/java/be/ugent/mmlab/rml/processor/concrete/CSVProcessor.java index 74cd784..ef5642a 100644 --- a/src/main/java/be/ugent/mmlab/rml/processor/concrete/CSVProcessor.java +++ b/src/main/java/be/ugent/mmlab/rml/processor/concrete/CSVProcessor.java @@ -4,7 +4,6 @@ import be.ugent.mmlab.rml.core.RMLMappingFactory; import be.ugent.mmlab.rml.core.RMLPerformer; import be.ugent.mmlab.rml.model.LogicalSource; -import be.ugent.mmlab.rml.model.SubjectMap; import be.ugent.mmlab.rml.model.TriplesMap; import be.ugent.mmlab.rml.processor.AbstractRMLProcessor; import com.csvreader.CsvReader; @@ -18,7 +17,6 @@ import net.antidot.semantic.rdf.model.impl.sesame.SesameDataSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.openrdf.model.Resource; /** * @@ -28,6 +26,8 @@ public class CSVProcessor extends AbstractRMLProcessor { private static Log log = LogFactory.getLog(RMLMappingFactory.class); + + //AD:That should not be on the core of RML processing.. private char getDelimiter(LogicalSource ls) { String d = RMLEngine.getFileMap().getProperty(ls.getIdentifier() + ".delimiter"); if (d == null) { diff --git a/src/main/java/be/ugent/mmlab/rml/processor/concrete/ConcreteRMLProcessorFactory.java b/src/main/java/be/ugent/mmlab/rml/processor/concrete/ConcreteRMLProcessorFactory.java index 877e45c..1acc101 100644 --- a/src/main/java/be/ugent/mmlab/rml/processor/concrete/ConcreteRMLProcessorFactory.java +++ b/src/main/java/be/ugent/mmlab/rml/processor/concrete/ConcreteRMLProcessorFactory.java @@ -25,6 +25,8 @@ public RMLProcessor create(QLTerm term) { return new CSVProcessor(); case JSONPATH_CLASS: return new JSONPathProcessor(); + case CSS3_CLASS: + return new CSS3Extractor(); } return null; } diff --git a/src/main/java/be/ugent/mmlab/rml/processor/concrete/XPathProcessor.java b/src/main/java/be/ugent/mmlab/rml/processor/concrete/XPathProcessor.java index 6a7d007..4123551 100644 --- a/src/main/java/be/ugent/mmlab/rml/processor/concrete/XPathProcessor.java +++ b/src/main/java/be/ugent/mmlab/rml/processor/concrete/XPathProcessor.java @@ -3,7 +3,6 @@ import be.ugent.mmlab.rml.core.RMLMappingFactory; import be.ugent.mmlab.rml.core.RMLPerformer; import be.ugent.mmlab.rml.model.TriplesMap; -import be.ugent.mmlab.rml.model.reference.ReferenceIdentifierImpl; import be.ugent.mmlab.rml.processor.AbstractRMLProcessor; import be.ugent.mmlab.rml.xml.XOMBuilder; import java.io.FileInputStream; @@ -17,7 +16,6 @@ import jlibs.xml.Namespaces; import jlibs.xml.sax.dog.NodeItem; import jlibs.xml.sax.dog.XMLDog; -import jlibs.xml.sax.dog.XPathResults; import jlibs.xml.sax.dog.expr.Expression; import jlibs.xml.sax.dog.expr.InstantEvaluationListener; import net.antidot.semantic.rdf.model.impl.sesame.SesameDataSet; diff --git a/src/main/java/be/ugent/mmlab/rml/vocabulary/Vocab.java b/src/main/java/be/ugent/mmlab/rml/vocabulary/Vocab.java index 5315a1f..830a66f 100644 --- a/src/main/java/be/ugent/mmlab/rml/vocabulary/Vocab.java +++ b/src/main/java/be/ugent/mmlab/rml/vocabulary/Vocab.java @@ -62,7 +62,8 @@ public enum QLTerm { XPATH_CLASS("XPath"), SQL_CLASS("SQL"), JSONPATH_CLASS("JSONPath"), - CSV_CLASS("CSV"); + CSV_CLASS("CSV"), + CSS3_CLASS("CSS3"); private String displayName; diff --git a/src/test/java/be/ugent/mmlab/rml/MapperTest.java b/src/test/java/be/ugent/mmlab/rml/MapperTest.java index cb9c6bf..cf263bc 100644 --- a/src/test/java/be/ugent/mmlab/rml/MapperTest.java +++ b/src/test/java/be/ugent/mmlab/rml/MapperTest.java @@ -103,6 +103,30 @@ public void testExample8() { assertTrue(assertMap(fileToRMLFile, fileToOutputFile)); } + /*public void testExample9() { + URL fileToRMLFile = getClass().getResource("/example9/html_href.rml.ttl"); + URL fileToOutputFile = getClass().getResource("/example9/html.output.ttl"); + assertTrue(assertMap(fileToRMLFile, fileToOutputFile)); + }*/ + + public void testExample10() { + URL fileToRMLFile = getClass().getResource("/example10/amazon.rml.ttl"); + URL fileToOutputFile = getClass().getResource("/example10/amazon.output.ttl"); + assertTrue(assertMap(fileToRMLFile, fileToOutputFile)); + } + + /*public void testExample11() { + URL fileToRMLFile = getClass().getResource("/example11/nmbs_station.rml.ttl"); + URL fileToOutputFile = getClass().getResource("/example11/nmbs_station.output.ttl"); + assertTrue(assertMap(fileToRMLFile, fileToOutputFile)); + } + + public void testExample12() { + URL fileToRMLFile = getClass().getResource("/example12/CEURWorkshopProceedings_test.rml.ttl"); + URL fileToOutputFile = getClass().getResource("/example12/CEURWorkshopProceedings.output.ttl"); + assertTrue(assertMap(fileToRMLFile, fileToOutputFile)); + }*/ + private boolean assertMap(URL mappingURL, URL outputURL) { try { RMLMapping mapping = RMLMappingFactory.extractRMLMapping(mappingURL.getFile()); diff --git a/src/test/resources/example10/amazon.html b/src/test/resources/example10/amazon.html new file mode 100644 index 0000000..4276b66 --- /dev/null +++ b/src/test/resources/example10/amazon.html @@ -0,0 +1,4649 @@ + + + + + + + + Codestin Search App + + + + + + + + + + +
+ +
+ + + + + + + + + + Industrial & Scientific + + + + Best Books of the Month + + + + Dresses + Shop Dresses + Shop All Clothing + Amazon Fashion + + + + Cloud Drive Photos + + + + Titanfall + + + + + + + + Spring Cleaning + + + + Create an Amazon Wedding Registry + + + + Veronica Mars + Veronica Mars + Veronica Mars + + + + Kindle Family Page + + + + Kindle Family Page + + + + XboxOne + + + + Luke Bryan + + + + The Spring Sportsmans Event + + + + Diaper + + + + + + + + +
+ + + + + + + +
+ +
+ + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + diff --git a/src/test/resources/example10/amazon.output.ttl b/src/test/resources/example10/amazon.output.ttl new file mode 100644 index 0000000..9c47b11 --- /dev/null +++ b/src/test/resources/example10/amazon.output.ttl @@ -0,0 +1,80 @@ + a ; + "Samsonite Lift Spinner 25 Inch Expandable Wheeled Luggage" ; + "$132.99 - $231.24" . + + a ; + "US Traveler Rio Two Piece Expandable Carry-On Luggage Set" ; + "$29.99 - $59.99" . + + a ; + "Samsonite 5 Piece Nested Luggage Set" ; + "$88.00 - $149.95" . + + a ; + "US Traveler New Yorker 4 Piece Luggage Set Expandable" ; + "$74.99 - $109.99" . + + a ; + "Samsonite LIFT 29\" Spinner Expandable" ; + "$119.99 - $299.99" . + + a ; + "Rockland 2 Piece Luggage Set" ; + "$29.99 - $49.99" . + + a ; + "Traveler's Choice Freedom II - 3-Piece Hardside Spinner/Rolling Luggage Set" ; + "$141.23 - $199.99" . + + a ; + "Rockland Luggage Four-Piece Luggage Set" ; + "$79.00 - $239.99" . + + a ; + "Traveler's Choice Luggage Toronto Three Piece Hardside Spinner Luggage" ; + "$159.24 - $199.99" . + + a ; + "Rockland Luggage 22 Inch Rolling Duffle Bag" ; + "$19.99 - $52.99" . + + a ; + "Rockland Luggage Melbourne 3 Piece Set" ; + "$118.62 - $178.99" . + + a ; + "American Tourister Luggage AT Pop Three-Piece Spinner Set" ; + "$129.48 - $191.95" . + + a ; + "Olympia Luggage 29\" 8 Pocket Rolling Duffel Bag" ; + "$32.95 - $84.28" . + + a ; + "Rockland Luggage Melbourne 20 Inch Expandable Carry On" ; + "$50.54 - $69.99" . + + a ; + "Camry 110lbs Pounds Luggage Scale with Temperature Sensor and Tare Function, Gift for Traveller" ; + "$4.40" . + + a ; + "$72.51 - $129.95" ; + "Olympia Luggage Tuscany 30 Inch Expandable Vertical Rolling Luggage Case" . + + + a ; + "$132.99 - $231.24" ; + "Samsonite Lift Spinner 25 Inch Expandable Wheeled Luggage" . + + a ; + "$29.99 - $59.99" ; + "US Traveler Rio Two Piece Expandable Carry-On Luggage Set" . + + a ; + "$88.00 - $149.95" ; + "Samsonite 5 Piece Nested Luggage Set" . + + a ; + "$74.99 - $109.99" ; + "US Traveler New Yorker 4 Piece Luggage Set Expandable" . \ No newline at end of file diff --git a/src/test/resources/example10/amazon.rml.ttl b/src/test/resources/example10/amazon.rml.ttl new file mode 100644 index 0000000..50c8e75 --- /dev/null +++ b/src/test/resources/example10/amazon.rml.ttl @@ -0,0 +1,78 @@ +@prefix rr: . +@prefix rml: . +@prefix ex: . +@prefix ql: . +@prefix xsd: . +@prefix rdfs: . +@prefix dcterms: . +@prefix tio: . +@prefix bibo: . +@prefix skos: . +@prefix opus: . +@prefix foaf: . +@prefix swc: . + +<#Results1Mapping> + rml:logicalSource + [ + rml:sourceName "/example10/amazon.html" ; + rml:iterator "div.fstRowGrid.prod.celwidget"; + rml:queryLanguage ql:CSS3 ; + ]; + + rr:subjectMap + [ + rr:template "http://example.com/html/result/{span.lrg.bold}"; + #wrong class + rr:class ex:Result + ]; + + rr:predicateObjectMap + [ + rr:predicate rdfs:label; + rr:objectMap [ + rml:reference "span.lrg.bold"; + ] + ]; + + rr:predicateObjectMap + [ + rr:predicate ex:costs; + rr:objectMap [ + rml:reference ".bld.lrg.red" + ] + ]. + + +<#Results2Mapping> + rml:logicalSource + [ + rml:sourceName "/example10/amazon.html" ; + rml:iterator "div.rsltGrid.prod.celwidget"; + rml:queryLanguage ql:CSS3 ; + ]; + + rr:subjectMap + [ + rr:template "http://example.com/html/result/{span.lrg.bold}"; + #wrong class + rr:class ex:Result + ]; + + rr:predicateObjectMap + [ + rr:predicate rdfs:label; + rr:objectMap [ + rml:reference "span.lrg.bold"; + ] + ]; + + rr:predicateObjectMap + [ + rr:predicate ex:costs; + rr:objectMap [ + rml:reference ".bld.lrg.red" + ] + ]. + +