繁体   English   中英

XPath:如何正确实现XpathResolver

[英]XPath: How to implement XpathResolver correctly

我想使用XPath从XML过滤信息。

XPathFactory factory = XPathFactory.newInstance();
     XPath xpath = factory.newXPath();
     Object result = null;
     // set the custom resolver to compares dates
     xpath.setXPathFunctionResolver(new DateValidatorContext(PubUtils.getInstance().parseDate(date), operator));
     try {    
      PubUtils.getInstance().printDOM(feed, System.out);
      XPathExpression expr = xpath.compile("//entry/content/artifact/resourceUri/text()");
   result = expr.evaluate(feed, XPathConstants.NODESET);
  } catch (XPathExpressionException e) {
   PublishService.logger.debug(e.getMessage());
   return null;
  }
     NodeList nodes = (NodeList) result;
     for (int i = 0; i < nodes.getLength(); i++) {
         System.out.println(nodes.item(i).getNodeValue()); 
     }

我实现了XPathResolver,它检查日期是否比给定日期(EQUALS / GREATER / LOWER)大。

import java.util.Date;
import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.xpath.XPathFunction;
import javax.xml.xpath.XPathFunctionException;
import javax.xml.xpath.XPathFunctionResolver;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import ....Operator;

/**
 * XPathFunctionResolver to compare dates
 * 
 */
public class DateValidatorContext implements XPathFunctionResolver {

 private static final QName name = new QName(null, "compare-date");
 private Date referenceDate = null; 
 Operator operator = Operator.EQUALS;

 /**
  * Sets the variables for comparison. Default comparison is equals
  * 
  * @param referenceDate
  *            date to compare to
  */
 public DateValidatorContext (Date referenceDate){
  this.referenceDate = referenceDate;
 }

 /**
  * Sets the variables for comparison
  * 
  * @param referenceDate
  *            date to compare to
  * @param operator
  *            type of operation to execute (EQUALS, GREATER, LOWER)
  */
 public DateValidatorContext (Date referenceDate, Operator operator){
  this.referenceDate = referenceDate;
  this.operator = operator;
 }

 public XPathFunction resolveFunction(QName name, int arity) {
  if (name.equals(DateValidatorContext.name) && arity == 1) {
   return new DateValidator(referenceDate, operator);
  }
  return null;
 }

 /**
  * XPathFunction to compare dates
  * 
  */
 public class DateValidator implements XPathFunction{

  private Date referenceDate = null; 
  Operator operator = Operator.EQUALS;

  /**
   * Set the values for comparison
   * 
   * @param referenceDate
   *            date to compare to
   * @param operator
   *            type of operation to execute (EQUALS, GREATER, LOWER)
   */
  public DateValidator (Date referenceDate, Operator operator){
   this.referenceDate = referenceDate;
   this.operator = operator;
  }

  public Object evaluate(List args) throws XPathFunctionException {
   if(args.size()!= 1){
    throw new XPathFunctionException("Wrong number of arguments to compare-date()");
   }

   Date feedItemDate;
      Object o = args.get(0);

      // perform conversions
      if (o instanceof String) feedItemDate = PubUtils.getInstance().parseDate((String) args.get(0));
      else if (o instanceof Boolean) feedItemDate = null;
      else if (o instanceof Double) feedItemDate = null;
      else if (o instanceof NodeList) {
          NodeList list = (NodeList) o;
          Node node = list.item(0);
          feedItemDate= PubUtils.getInstance().parseDate(node.getTextContent());
      }
      else {
          throw new XPathFunctionException("Could not convert argument type");
      }

      if(referenceDate != null && feedItemDate != null){
       int dateCompare = feedItemDate.compareTo(referenceDate);
       switch(operator){
        case EQUALS: 
         if(dateCompare == 0){
          return Boolean.TRUE;
         }         
         break;
        case GREATER:
         if(dateCompare > 0){
          return Boolean.TRUE;
         }         
         break;
        case LOWER:
         if(dateCompare < 0){
          return Boolean.TRUE;
         }         
         break;
        default: 
         break;
       }
      }

   return Boolean.FALSE;
  }
 }
}

问题在于当前表达式

"//entry/content/artifact/resourceUri/text()"

我从XML获取所有内容。 如何解决此问题,以便仅从XML获取我需要的信息?

样本XML:

<?xml version="1.0" encoding="UTF-8"?>
<recentArtifactsFeed>
 <entry>
  <updated>2010-07-08T00:54:22.859Z</updated>
  <content lang="english" type="application/xml">
    <artifact><resourceUri>../types/_WDKRIYorEd-hG9AeAoU8_g</resourceUri></artifact>
  </content>
 </entry>
</recentArtifactsFeed>

我刚刚测试了您的xpathExpression(“ // entry / content / artifact / resourceUri / text()”),没有使用XPathFunctionResolver,这给出了预期的结果。

我无法使用XPathFunctionResolver进行测试,因为代码不完整(Operator,PubUtils等),但是我检查了Javadoc:

特别是,仅针对另一个命名空间中的函数(具有显式前缀的函数)调用解析器。 这意味着您不能使用XPathFunctionResolver来实现XML签名语法和处理之类的规范,这些规范在同一名称空间中扩展了XPath 1.0的功能库。 这是解析器设计的结果。

以下也提供了一个很好的开始: http : //xml.apache.org/xalan-j/xpath_apis.html#functionresolver

简而言之,使用函数解析器需要三个步骤:

  1. 创建XPathFunction
  2. 创建XPathFunctionResolver
  3. 创建NamespaceContext

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM