View Javadoc

1   /*
2    * $Id: JXPathExtractor.java 7963 2007-08-21 08:53:15Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.transformers.xml;
12  
13  import org.mule.transformers.AbstractTransformer;
14  import org.mule.umo.transformer.TransformerException;
15  
16  import java.util.ArrayList;
17  import java.util.List;
18  
19  import org.apache.commons.jxpath.JXPathContext;
20  import org.dom4j.Document;
21  import org.dom4j.DocumentHelper;
22  import org.dom4j.Node;
23  import org.dom4j.XPath;
24  
25  /**
26   * The JXPathExtractor is a simple transformer that evaluates an xpath expression
27   * against the given bean and that returns the result. <p/> By default, a single
28   * result will be returned. If multiple values are expected, set the
29   * {@link #singleResult} property to <code>false</code>. In this case a
30   * {@link List} of values will be returned. Note the property is currently ignored
31   * for non-String/XML payloads.
32   */
33  public class JXPathExtractor extends AbstractTransformer
34  {
35  
36      private volatile String expression;
37  
38      private volatile boolean singleResult = true;
39  
40      /**
41       * Evaluate the expression in the context of the given object and returns the
42       * result. If the given object is a string, it assumes it is an valid xml and
43       * parses it before evaluating the xpath expression.
44       */
45      public Object doTransform(Object src, String encoding) throws TransformerException
46      {
47          try
48          {
49              Object result;
50              if (src instanceof String)
51              {
52                  Document doc = DocumentHelper.parseText((String)src);
53                  if (singleResult)
54                  {
55                      result = doc.valueOf(expression);
56                  }
57                  else
58                  {
59                      XPath xpath = doc.createXPath(expression);
60                      // TODO handle non-list cases, see
61                      // http://www.dom4j.org/apidocs/org/dom4j/XPath.html#evaluate(java.lang.Object)
62                      List obj = (List)xpath.evaluate(doc);
63                      result = new ArrayList(obj.size());
64                      for (int i = 0; i < obj.size(); i++)
65                      {
66                          final Node node = (Node)obj.get(i);
67                          ((List)result).add(node.getText());
68                      }
69                  }
70              }
71              else
72              {
73                  JXPathContext context = JXPathContext.newContext(src);
74                  result = context.getValue(expression);
75              }
76              return result;
77          }
78          catch (Exception e)
79          {
80              throw new TransformerException(this, e);
81          }
82      }
83  
84      /**
85       * @return Returns the expression.
86       */
87      public String getExpression()
88      {
89          return expression;
90      }
91  
92      /**
93       * @param expression The expression to set.
94       */
95      public void setExpression(String expression)
96      {
97          this.expression = expression;
98      }
99  
100     /**
101      * Should a single value be returned.
102      * 
103      * @return value
104      */
105     public boolean isSingleResult()
106     {
107         return singleResult;
108     }
109 
110     /**
111      * If multiple results are expected from the {@link #expression} evaluation, set
112      * this to false.
113      * 
114      * @param singleResult flag
115      */
116     public void setSingleResult(boolean singleResult)
117     {
118         this.singleResult = singleResult;
119     }
120 }