2010-07-09 5 views
0

XPath를 사용하여 XML의 정보를 필터링하고 싶습니다.XPath : XpathResolver를 올바르게 구현하는 방법

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()); 
    } 

주어진 날짜보다 (EQUALS/GREATER/LOWER) 날짜인지 확인하는 XPathResolver를 구현했습니다.

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> 

답변

0

내가 그냥하는 xpathExpression 테스트 ("// 항목/내용/유물/resourceUri가/텍스트()")는 XPathFunctionResolver없이, 이것은 예상 된 결과를 제공합니다.

코드 (운영자, PubUtils, ...) 완전하지 않기 때문에 내가의 XPathFunctionResolver로 테스트 할 수 없습니다,하지만 난이 javadoc의 확인 : 특히

를, 리졸버는 요구 입니다 함수는 다른 네임 스페이스 ( 명시 적 접두사로 작동)에서 작동합니다. 이것은 당신이 이 같은 네임 스페이스에 XPath를 1.0의 함수 라이브러리를 확장 XML-서명 구문 및 처리와 같은 XPathFunctionResolver 구현 에 사양을 사용할 수 없음을 의미합니다. 이는 해결자를 설계 한 결과입니다.

다음도 좋은 시작 제공 :

  • XPathFunctionResolver를 만들
  • NamespaceContext
  • 을 만들 XPathFunction을 만들

    1. : 한마디로 http://xml.apache.org/xalan-j/xpath_apis.html#functionresolver

      를, 그것은 functionresolvers를 사용하는 세 가지 조치를 취하고

    +0

    네임 스페이스에서만 작동합니다 ... 나쁘지 만, 날짜를 확인하려면 수동 구현을해야했습니다. 응답 해 주셔서 감사합니다 :) – Gary

    관련 문제