You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pig.apache.org by da...@apache.org on 2016/07/16 20:47:47 UTC

svn commit: r1752995 - in /pig/trunk: CHANGES.txt contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/evaluation/xml/XPath.java contrib/piggybank/java/src/test/java/org/apache/pig/piggybank/test/evaluation/xml/XPathTest.java

Author: daijy
Date: Sat Jul 16 20:47:47 2016
New Revision: 1752995

URL: http://svn.apache.org/viewvc?rev=1752995&view=rev
Log:
PIG-4938: [PiggyBank] XPath returns empty values when using aggregation method

Modified:
    pig/trunk/CHANGES.txt
    pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/evaluation/xml/XPath.java
    pig/trunk/contrib/piggybank/java/src/test/java/org/apache/pig/piggybank/test/evaluation/xml/XPathTest.java

Modified: pig/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/pig/trunk/CHANGES.txt?rev=1752995&r1=1752994&r2=1752995&view=diff
==============================================================================
--- pig/trunk/CHANGES.txt (original)
+++ pig/trunk/CHANGES.txt Sat Jul 16 20:47:47 2016
@@ -36,6 +36,8 @@ OPTIMIZATIONS
  
 BUG FIXES
 
+PIG-4938: [PiggyBank] XPath returns empty values when using aggregation method (nkollar via daijy)
+
 PIG-4896: Param substitution ignored when redefined (knoguchi)
 
 PIG-2315: Make as clause work in generate (daijy via knoguchi)

Modified: pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/evaluation/xml/XPath.java
URL: http://svn.apache.org/viewvc/pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/evaluation/xml/XPath.java?rev=1752995&r1=1752994&r2=1752995&view=diff
==============================================================================
--- pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/evaluation/xml/XPath.java (original)
+++ pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/evaluation/xml/XPath.java Sat Jul 16 20:47:47 2016
@@ -16,8 +16,11 @@ package org.apache.pig.piggybank.evaluat
 import java.io.IOException;
 import java.io.StringReader;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.xpath.XPathFactory;
@@ -49,8 +52,7 @@ public class XPath extends EvalFunc<Stri
     
     private static boolean cache = true;
     private static boolean ignoreNamespace = true;
-    public static final String EMPTY_STRING = "";
-    
+
     /**
      * input should contain: 1) xml 2) xpath 
      *                       3) optional cache xml doc flag 
@@ -95,8 +97,13 @@ public class XPath extends EvalFunc<Stri
                 return null;
             }
             
-            if(input.size() > 2)
+            if(input.size() > 2) {
                 cache = (Boolean) input.get(2);
+            }
+
+            if (input.size() > 3) {
+                ignoreNamespace = (Boolean) input.get(3);
+            }
 
             if (!cache || xpath == null || !xml.equals(this.xml)) {
                 final InputSource source = new InputSource(new StringReader(xml));
@@ -104,6 +111,7 @@ public class XPath extends EvalFunc<Stri
                 this.xml = xml; // track the xml for subsequent calls to this udf
 
                 final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+                dbf.setNamespaceAware(!ignoreNamespace);
                 final DocumentBuilder db = dbf.newDocumentBuilder();
 
                 this.document = db.parse(source);
@@ -112,14 +120,32 @@ public class XPath extends EvalFunc<Stri
 
                 this.xpath = xpathFactory.newXPath();
 
+                if (!ignoreNamespace) {
+                    xpath.setNamespaceContext(new NamespaceContext() {
+                        @Override
+                        public String getNamespaceURI(String prefix) {
+                            if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
+                                return document.lookupNamespaceURI(null);
+                            } else {
+                                return document.lookupNamespaceURI(prefix);
+                            }
+                        }
+
+                        @Override
+                        public String getPrefix(String namespaceURI) {
+                            return document.lookupPrefix(namespaceURI);
+                        }
+
+                        @Override
+                        public Iterator getPrefixes(String namespaceURI) {
+                            return null;
+                        }
+                    });
+                }
             }
 
             String xpathString = (String) input.get(1);
 
-            if (ignoreNamespace) {
-                xpathString = createNameSpaceIgnoreXpathString(xpathString);
-            }
-
             final String value = xpath.evaluate(xpathString, document);
 
             return value;
@@ -165,34 +191,6 @@ public class XPath extends EvalFunc<Stri
         }
         return true;
     }
-    
-    
-    /**
-     * Returns a new the xPathString by adding additional parameters 
-     * in the existing xPathString for ignoring the namespace during compilation.
-     * 
-     * @param String xpathString
-     * @return String modified xpathString
-     */
-    private String createNameSpaceIgnoreXpathString(final String xpathString) {
-        final String QUERY_PREFIX = "//*";
-        final String LOCAL_PREFIX = "[local-name()='";
-        final String LOCAL_POSTFIX = "']";
-        final String SPLITTER = "/";
-
-        try {
-            String xpathStringWithLocalName = EMPTY_STRING;
-            String[] individualNodes = xpathString.split(SPLITTER);
-
-            for (String node : individualNodes) {
-                xpathStringWithLocalName = xpathStringWithLocalName.concat(QUERY_PREFIX + LOCAL_PREFIX + node
-                        + LOCAL_POSTFIX);
-            }
-            return xpathStringWithLocalName;
-        } catch (Exception ex) {
-            return xpathString;
-        }
-    }
 
     /**
      * Returns argument schemas of the UDF.

Modified: pig/trunk/contrib/piggybank/java/src/test/java/org/apache/pig/piggybank/test/evaluation/xml/XPathTest.java
URL: http://svn.apache.org/viewvc/pig/trunk/contrib/piggybank/java/src/test/java/org/apache/pig/piggybank/test/evaluation/xml/XPathTest.java?rev=1752995&r1=1752994&r2=1752995&view=diff
==============================================================================
--- pig/trunk/contrib/piggybank/java/src/test/java/org/apache/pig/piggybank/test/evaluation/xml/XPathTest.java (original)
+++ pig/trunk/contrib/piggybank/java/src/test/java/org/apache/pig/piggybank/test/evaluation/xml/XPathTest.java Sat Jul 16 20:47:47 2016
@@ -151,6 +151,27 @@ public class XPathTest {
     }
 
     @Test
+    public void testExecTupleWithDontIgnoreNamespace() throws Exception {
+
+        final XPath xpath = new XPath();
+
+        final Tuple tuple = mock(Tuple.class);
+
+        when(tuple.get(0)).thenReturn("<?xml version='1.0'?>\n" +
+                "<foo:document xmlns:foo=\"http://apache.org/foo\" xmlns:bar=\"http://apache.org/bar\">" +
+                "<bar:element>MyBar</bar:element>" +
+                "</foo:document>");
+
+        when(tuple.size()).thenReturn(4);
+        when(tuple.get(2)).thenReturn(true);
+        when(tuple.get(3)).thenReturn(false);
+
+        when(tuple.get(1)).thenReturn("/foo:document/bar:element");
+        assertEquals("MyBar", xpath.exec(tuple));
+
+    }
+
+    @Test
     public void testExecTupleWithElementNodeWithComplexNameSpace() throws Exception {
 
         final XPath xpath = new XPath();
@@ -210,7 +231,31 @@ public class XPathTest {
         assertEquals("4 stars3.5 stars4 stars4.2 stars3.5 stars", xpath.exec(tuple));
 
     }
-    
+
+    @Test
+    public void testFunctionInXPath() throws Exception {
+
+        final XPath xpath = new XPath();
+
+        final Tuple tuple = mock(Tuple.class);
+
+        when(tuple.get(0)).thenReturn("<Aa name=\"test1\">" +
+                "<Bb Cc=\"1\"/>" +
+                "<Bb Cc=\"1\"/>" +
+                "<Bb Cc=\"1\"/>" +
+                "<Bb Cc=\"1\"/>" +
+                "<Dd>test2</Dd>" +
+                "</Aa>");
+
+        when(tuple.size()).thenReturn(4);
+        when(tuple.get(1)).thenReturn("sum(Aa/Bb/@Cc)");
+        when(tuple.get(2)).thenReturn(true);
+        when(tuple.get(3)).thenReturn(true);
+
+        assertEquals("4", xpath.exec(tuple));
+
+    }
+
     @Ignore //--optional test
     @Test 
     public void testCacheBenefit() throws Exception{