From 468c757dd7133be9127edc4285457b8e75f83e55 Mon Sep 17 00:00:00 2001 From: Yoko Harada Date: Thu, 1 Apr 2010 12:58:02 -0400 Subject: [PATCH] Take 2. Fix failures of xpath with custom object. By this change, namespace for xpath function has been added to NokogiriNamespaceContext. --- ext/java/nokogiri/XmlXpathContext.java | 19 +++++++ .../internals/NokogiriNamespaceContext.java | 56 +++++++++++++------ 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/ext/java/nokogiri/XmlXpathContext.java b/ext/java/nokogiri/XmlXpathContext.java index 10229d2e3cb..432d0f3f83b 100644 --- a/ext/java/nokogiri/XmlXpathContext.java +++ b/ext/java/nokogiri/XmlXpathContext.java @@ -1,5 +1,7 @@ package nokogiri; +import java.util.Set; + import nokogiri.internals.NokogiriNamespaceContext; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathExpression; @@ -36,6 +38,12 @@ public IRubyObject evaluate(ThreadContext context, IRubyObject expr, IRubyObject String src = expr.convertToString().asJavaString(); try { if(!handler.isNil()) { + if (!isContainsPrefix(src)) { + Set methodNames = handler.getMetaClass().getMethods().keySet(); + for (String name : methodNames) { + src = src.replaceAll(name, NokogiriNamespaceContext.NOKOGIRI_PREFIX+":"+name); + } + } xpath.setXPathFunctionResolver(new NokogiriXPathFunctionResolver(handler)); } XPathExpression xpathExpression = xpath.compile(src); @@ -44,6 +52,17 @@ public IRubyObject evaluate(ThreadContext context, IRubyObject expr, IRubyObject throw new RaiseException(XmlSyntaxError.getXPathSyntaxError(context, xpee)); } } + + private boolean isContainsPrefix(String str) { + Set prefixes = ((NokogiriNamespaceContext)xpath.getNamespaceContext()).getAllPrefixes(); + for (String prefix : prefixes) { + if (str.contains(prefix + ":")) { + return true; + } + } + return false; + } + @JRubyMethod public IRubyObject evaluate(ThreadContext context, IRubyObject expr) { diff --git a/ext/java/nokogiri/internals/NokogiriNamespaceContext.java b/ext/java/nokogiri/internals/NokogiriNamespaceContext.java index 32333841ade..cc7a065c56b 100644 --- a/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +++ b/ext/java/nokogiri/internals/NokogiriNamespaceContext.java @@ -1,31 +1,36 @@ package nokogiri.internals; +import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.Map.Entry; + import javax.xml.XMLConstants; import javax.xml.namespace.NamespaceContext; -public class NokogiriNamespaceContext implements NamespaceContext{ - - Hashtable register; +public class NokogiriNamespaceContext implements NamespaceContext { + public static final String NOKOGIRI_PREFIX = "nokogiri"; + public static final String NOKOGIRI_URI = "http://www.nokogiri.org/default_ns/ruby/extensions_functions"; + + private Hashtable register; - public NokogiriNamespaceContext(){ + public NokogiriNamespaceContext() { this.register = new Hashtable(); + register.put(NOKOGIRI_PREFIX, NOKOGIRI_URI); } public String getNamespaceURI(String prefix) { -// System.out.println("Asked for " + prefix); + if (prefix == null) { + throw new IllegalArgumentException(); + } String uri = this.register.get(prefix); - if(uri != null) { -// System.out.println("Returned "+uri); + if (uri != null) { return uri; } -// System.out.println("Returned another url"); - - if(prefix == null) { - throw new IllegalArgumentException(); - } else if(prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) { + if (prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) { uri = this.register.get(XMLConstants.XMLNS_ATTRIBUTE); return (uri == null) ? XMLConstants.XMLNS_ATTRIBUTE_NS_URI : uri; } @@ -33,17 +38,34 @@ public String getNamespaceURI(String prefix) { return XMLConstants.NULL_NS_URI; } - public String getPrefix(String uri){ + public String getPrefix(String uri) { + if (uri == null) { + throw new IllegalArgumentException("uri is null"); + } else if (uri.equals(NOKOGIRI_URI)) { + return NOKOGIRI_PREFIX; + } return null; } - public Iterator getPrefixes(String uri){ - return null; + public Iterator getPrefixes(String uri) { + if (register == null) return null; + Set> entries = register.entrySet(); + List list = new ArrayList(); + for (Entry entry : entries) { + if (uri.equals(entry.getValue())) { + list.add(entry.getKey()); + } + } + return list.iterator(); + } + + public Set getAllPrefixes() { + if (register == null) return null; + return register.keySet(); } - public void registerNamespace(String prefix, String uri){ + public void registerNamespace(String prefix, String uri) { if("xmlns".equals(prefix)) prefix = ""; -// System.out.println("Registered prefix "+prefix+" with uri " + uri); this.register.put(prefix, uri); } }