@Override
  protected Object doExec(Element element, Object scope, String expression, Object... arguments) throws TemplateException
  {
    if(expression.isEmpty()) {
      throw new TemplateException("Invalid ATTR operand. Attribute property path expression is empty.");
    }
    Set<Attr> syntheticAttributes = new HashSet<Attr>();

    PairsList pairs = new PairsList(expression);
    for(Pair pair : pairs) {
      // accordingly this operator expression syntax first value is attribute name and second is property path
      String value = content.getString(scope, pair.second());
      if(value != null) {
        syntheticAttributes.add(new AttrImpl(pair.first(), value));
      }
    }

    return syntheticAttributes;
  }
@ Override protected Object doExec ( Element element , Object scope , String expression , Object ... arguments ) throws TemplateException { if ( expression . isEmpty ( ) ) { throw new TemplateException ( "Invalid ATTR operand. Attribute property path expression is empty." ) ; } Set < Attr > syntheticAttributes = new HashSet < Attr > ( ) ; PairsList pairs = new PairsList ( expression ) ; for ( Pair pair : pairs ) { String value = content . getString ( scope , pair . second ( ) ) ; if ( value != null ) { syntheticAttributes . add ( new AttrImpl ( pair . first ( ) , value ) ) ; } } return syntheticAttributes ; }
Execute ATTR operator. Expression argument is set of attribute name / property path pairs. Property path is used to
retrieve content value that is converted to string and used as attribute value.

@param element context element, unused,
@param scope scope object,
@param expression set of attribute name / property path pairs,
@param arguments optional arguments, unused.
@return always returns null for void.
@throws TemplateException if expression is empty or not well formatted or if requested content value is undefined.