Browse Source

xml: integration with css-selectors

Ranides Atterwim 10 years ago
parent
commit
6a70a6dd0f

+ 2 - 0
assira/src/main/java/net/ranides/assira/xml/XMLElement.java

@@ -113,5 +113,7 @@ public interface XMLElement extends Wrapper<String> {
     
     XMLElement apply(Transformer transformer) throws XMLException;
     
+    XMLElement apply(XMLElement transformer) throws XMLException;
+    
         
 }

+ 0 - 23
assira/src/main/java/net/ranides/assira/xml/XMLQuery.java

@@ -13,20 +13,13 @@ import java.io.InputStream;
 import java.io.Reader;
 import java.io.StringReader;
 import java.net.URI;
-import java.util.function.Predicate;
-import java.util.regex.Pattern;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
 import net.ranides.assira.collection.query.CQueryBuilder;
 import net.ranides.assira.functional.CheckedSupplier;
 import net.ranides.assira.trace.ExceptionUtils;
 import net.ranides.assira.xml.impl.CElements;
-import net.ranides.assira.xml.impl.W3Selectors;
 import net.ranides.assira.xml.impl.W3Element;
 import org.w3c.dom.Node;
 import org.xml.sax.InputSource;
@@ -89,22 +82,6 @@ public final class XMLQuery {
         return new CElements(CQueryBuilder.fromArray(elements));
     }
     
-    public static Transformer $tr(XMLElement xsl) {
-        try {
-            return TransformerFactory.newInstance().newTransformer(new DOMSource(xsl.node()));
-        } catch (TransformerConfigurationException cause) {
-            throw new XMLException(cause);
-        }
-    }
-    
-    public static XMLSelector $text(String regex) {
-        return new W3Selectors.Text(regex);
-    }
-    
-    public static XMLSelector $text(Predicate<String> predicate) {
-        return new W3Selectors.Text(predicate);
-    }
-    
     private static DocumentBuilder builder() throws ParserConfigurationException {
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
         factory.setNamespaceAware(false);

+ 12 - 0
assira/src/main/java/net/ranides/assira/xml/XMLSelector.java

@@ -26,5 +26,17 @@ public interface XMLSelector extends Function<XMLContext, XMLElements>, Predicat
     static XMLSelector compile(String selector) {
         return W3Selectors.compile(selector);
     }
+    
+    static XMLSelector css(String selector) {
+        return W3Selectors.css(selector);
+    }
+    
+    static XMLSelector xpath(String selector) {
+        return W3Selectors.xpath(selector);
+    }
+    
+    static XMLSelector text(String selector) {
+        return W3Selectors.text(selector);
+    }
 
 }

+ 120 - 0
assira/src/main/java/net/ranides/assira/xml/impl/CElement.java

@@ -0,0 +1,120 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.xml.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import net.ranides.assira.xml.XMLElement;
+import org.w3c.dom.Attr;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import se.fishtank.css.selectors.dom.DOMNode;
+
+/**
+ * Kopia klasy "W3CNode" z biblioteki css-selectors. 
+ * "W3Element" dziedziczy z tej klasy aby uniknąć podwójnego wrapowania "Node" w selektorach CSS.
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public abstract class CElement implements DOMNode<W3Element, Node>, XMLElement {
+
+    protected final Node node;
+
+    public CElement(Node node) {
+        this.node = node;
+    }
+
+    @Override
+    public Node getUnderlying() {
+        return node;
+    }
+
+    @Override
+    public DOMNode.Type getType() {
+        switch (node.getNodeType()) {
+        case Node.DOCUMENT_NODE:
+            return DOMNode.Type.DOCUMENT;
+        case Node.ELEMENT_NODE:
+            return DOMNode.Type.ELEMENT;
+        case Node.TEXT_NODE:
+            return DOMNode.Type.TEXT;
+        default:
+            return DOMNode.Type.OTHER;
+        }
+    }
+
+    @Override
+    public String getData() {
+        if (node.getNodeType() == Node.ELEMENT_NODE) {
+            return node.getNodeName();
+        }
+
+        return node.getNodeValue();
+    }
+
+    @Override
+    public Map<String, String> getAttributes() {
+        NamedNodeMap namedNodeMap = node.getAttributes();
+        if (namedNodeMap == null) {
+            return null;
+        }
+
+        HashMap<String, String> attrs = new HashMap<>();
+
+        int len = namedNodeMap.getLength();
+        for (int i = 0; i < len; ++i) {
+            Attr attr = (Attr) namedNodeMap.item(i);
+            attrs.put(attr.getName(), attr.getValue());
+        }
+
+        return attrs;
+    }
+
+    @Override
+    public W3Element getFirstChild() {
+        return wrap(node.getFirstChild());
+    }
+
+    @Override
+    public W3Element getPreviousSibling() {
+        return wrap(node.getPreviousSibling());
+    }
+
+    @Override
+    public W3Element getNextSibling() {
+        return wrap(node.getNextSibling());
+    }
+
+    @Override
+    public W3Element getParentNode() {
+        return wrap(node.getParentNode());
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (this == other) {
+            return true;
+        }
+
+        if (other == null || getClass() != other.getClass()) {
+            return false;
+        }
+
+        CElement that = (CElement) other;
+        return Objects.equals(node, that.node);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(node);
+    }
+
+    private W3Element wrap(Node n) {
+        return n == null ? null : new W3Element(n);
+    }
+
+}

+ 15 - 4
assira/src/main/java/net/ranides/assira/xml/impl/W3Element.java

@@ -17,7 +17,9 @@ import java.util.function.Predicate;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
 import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMResult;
 import javax.xml.transform.dom.DOMSource;
 
@@ -38,14 +40,12 @@ import net.ranides.assira.xml.*;
  *
  * @author Ranides Atterwim <ranides@gmail.com>
  */
-public class W3Element implements XMLElement {
+public class W3Element extends CElement implements XMLElement {
     
     private static final IClass TYPE = IClass.typeinfo(String.class);
     
-    protected final Node node;
-    
     protected W3Element(Node node) {
-        this.node = node;
+        super(node);
     }
     
     public static W3Element wrap(Node node) {
@@ -351,6 +351,17 @@ public class W3Element implements XMLElement {
             throw new XMLException(cause);
         }
     }
+
+    @Override
+    public XMLElement apply(XMLElement transformer) throws XMLException {
+        try {
+            return apply(TransformerFactory.newInstance().newTransformer(new DOMSource(transformer.node())));
+        } catch (TransformerConfigurationException cause) {
+            throw new XMLException(cause);
+        }
+    }
+    
+    
     
     static XMLElement $element(Node node) {
         return null == node ? null : new W3Element(node);

+ 34 - 30
assira/src/main/java/net/ranides/assira/xml/impl/W3Selectors.java

@@ -25,7 +25,6 @@ import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import se.fishtank.css.selectors.Selectors;
-import se.fishtank.css.selectors.dom.W3CNode;
 import se.fishtank.css.selectors.matching.SelectorMatcher;
 import se.fishtank.css.selectors.selector.Selector;
 
@@ -40,41 +39,49 @@ public final class W3Selectors {
         /* utility class */
     }
 
-    public static XMLSelector compile(String text) {
-        if(text.startsWith("? ")) {
-            return compileXP(text.substring(2));
+    public static XMLSelector compile(String selector) {
+        if(isxpath(selector)) {
+            return xpath(selector.substring(2));
         }
-        if(isTag(text)) {
-            return new Name(text);
+        if(isname(selector)) {
+            return new Name(selector);
         }
-        return compileCSS(text);
+        return css(selector);
     }
     
-    private static boolean isTag(String name) {
-        if(name.trim().equals("*")) {
+    public static XMLSelector css(String selector) {
+        return new CSS(selector);
+    }
+    
+    public static XMLSelector xpath(String selector) {
+        return new XPath(selector);
+    }
+    
+    public static XMLSelector text(String selector) {
+        return new Text(selector);
+    }
+
+    private static boolean isxpath(String selector) {
+        return selector.startsWith("? ");
+    }
+    
+    private static boolean isname(String selector) {
+        if(selector.trim().equals("*")) {
             return true;
         }
-        for(int i=0,n=name.length(); i<n; i++) {
-            if( !isTag(name.charAt(i))) {
+        for(int i=0,n=selector.length(); i<n; i++) {
+            if( !isname(selector.charAt(i))) {
                 return false;
             }
         }
         return true;
     }
     
-    private static boolean isTag(char cn) {
+    private static boolean isname(char cn) {
         return (cn=='-') || (cn>='a' && cn<='z') || (cn>='A' && cn<='Z');
     }
     
-    public static XMLSelector compileCSS(String selector) {
-        return new CSS(selector);
-    }
-    
-    public static XMLSelector compileXP(String selector) {
-        return new XPath(selector);
-    }
-
-    public static final class Text implements XMLSelector {
+    static final class Text implements XMLSelector {
         
         private final Predicate<String> predicate;
 
@@ -100,7 +107,7 @@ public final class W3Selectors {
     
     }
     
-    public static final class Name implements XMLSelector {
+    static final class Name implements XMLSelector {
         
         private final String name;
 
@@ -133,9 +140,9 @@ public final class W3Selectors {
     
     }
     
-    private static final class CSS implements XMLSelector {
+    static final class CSS implements XMLSelector {
         
-        private static final SelectorMatcher<W3CNode> MATCHER = new SelectorMatcher<>();
+        private static final SelectorMatcher<W3Element> MATCHER = new SelectorMatcher<>();
         
         private final List<Selector> scanner;
         
@@ -145,18 +152,17 @@ public final class W3Selectors {
 
         @Override
         public XMLElements apply(XMLContext c) {
-            W3CNode node = new W3CNode(c.node().node());
-            return new CElements(new Selectors<>(node).querySelectorAll(scanner));
+            return new CElements(new Selectors<>((W3Element)c.node()).querySelectorAll(scanner));
         }
 
         @Override
         public boolean test(XMLContext c) {
-            return MATCHER.matchesSelectors(scanner, new W3CNode(c.node().node()));
+            return MATCHER.matchesSelectors(scanner, (W3Element)c.node());
         }
         
     }
     
-    private static final class XPath implements XMLSelector {
+    static final class XPath implements XMLSelector {
         
         private final XPathExpression xpe;
 
@@ -189,8 +195,6 @@ public final class W3Selectors {
             }
         }
         
-        
-        
     }
    
 }