Download - Forum

User Guide Content

  1. Necessary Previous Knowledge
  2. Classic "Hello World" with SAX
  3. Classic "Hello World" with JColtrane
  4. Basic Annotation Conditions
  5. Filtering Element Options
  6. More Filtering Options
  7. Making Your Own Filter Conditions
  8. Receiving Parameters from JColtrane
  9. Extending Parsing Process

Help this project

Filtering Element Options

To facilitate the process of parsing, JColtrane offer some options to filter the elements from XML according to user desire. To ilustrate the options, we will use the XML code bellow:

<?xml version="1.0" encoding="UTF-8"?>

<beanDescriptor>

      <line>

            <property  mandatory="true" page="4" language="pt" />           

            <property2  mandatory="false"  language="pt" />

      </line>

</beanDescriptor>

Following the steps presented in section Classic "Hello World" with JColtrane,

let's build a basic class to execute some action when starting or ending a element:

public class StartAndEndElemetAction {

      @StartElement

      public void executeInStartElement(@CurrentBranch String currentBranch){

            System.out.println(currentBranch);

            System.out.println("Executing something in start element\n");

      }

 

      @EndElement

      public void executeInEndElement(@CurrentBranch String currentBranch){

            System.out.println(currentBranch);

            System.out.println("Executing something in end element\n");

      }

}

Now, we code a class passing the above class to JColtraneXMLHandler:

public class FilteringTest {

      public static void main(String[] args) {

            SAXParser parser=null;

            try {

                  parser= SAXParserFactory.newInstance().newSAXParser();

            } catch (ParserConfigurationException e) {

                  e.printStackTrace();

            } catch (SAXException e) {

                  e.printStackTrace();

            }

 

            File file=new File("examples\\example2\\Example2.xml");

            if(parser!=null){

                  InputSource input=new InputSource(file.getAbsolutePath());

                  try {

                        parser.parse(input,new JColtraneXMLHandler(new StartAndEndElemetAction()));

                  } catch (SAXException e) {

                        e.printStackTrace();

                  } catch (IOException e) {

                        e.printStackTrace();

                  }

            }

      }

}

Running the above class, system print:

/beanDescriptor/
Executing something in start element

/beanDescriptor/line/
Executing something in start element

/beanDescriptor/line/property/
Executing something in start element

/beanDescriptor/line/property/
Executing something in end element

/beanDescriptor/line/property2/
Executing something in start element

/beanDescriptor/line/property2/
Executing something in end element

/beanDescriptor/line/
Executing something in end element

/beanDescriptor/
Executing something in end element

As you can see, JColtrane make what we want: execute the methods when starting or ending any element. But let's say that you would like to execute the first method just when the element with a tag named "line" starts and the second method just execute when any element with a tag started with the suffix "property" ends . To do this, we will make the highlitgted modifications in StartAndEndElementAction's code:

public class StartAndEndElemetAction {

      @StartElement(tag="line")

      public void executeInStartElement(@CurrentBranch String currentBranch){

            System.out.println(currentBranch);

            System.out.println("Executing something in start element\n");

      }

 

      @EndElement(tag="property.*")

      public void executeInEndElement(@CurrentBranch String currentBranch){

            System.out.println(currentBranch);

            System.out.println("Executing something in end element\n");

      }

}

Executing FilteringTest again, system prints:

/beanDescriptor/line/
Executing something in start element

/beanDescriptor/line/property/
Executing something in end element

/beanDescriptor/line/property2/
Executing something in end elemen

As you can see, JColtrane have done exactly we want. In first method we put the property tag with the value "line". In second method we put the value "property.*". This last value is a regular expression. So, you can use a regular expressions (regex from JAVA) to filter elements.

Beside the tag property, you can use uri and localName properties too. those properties receive, respectively, uri and local name property from the element.

Let's consider now, that you want execute a method when a element is ending and element has an attribute with name "mandatory". You want to execute another method in a similar condition, but you want one more condition, you want that element contain an attribute with name "page" and value 4. Besides, you want another method to execute another method in an ending element if any attribute with value "pt". To do this, we write the class bellow:

public class EndElemetAction {

      @EndElement(attributes={@ContainAttribute(name="mandatory")})

      public void executeInEndElement1(@CurrentBranch String currentBranch){

            System.out.println(currentBranch);

            System.out.println("Executing something in end element with attribute mandatory\n");

      }

     

      @EndElement(attributes={@ContainAttribute(name="mandatory"),@ContainAttribute(name="page",value="4")})

      public void executeInEndElement2(@CurrentBranch String currentBranch){

            System.out.println(currentBranch);

            System.out.println("Executing something in end element with some attribute with name mandatory and another with name page and value 4\n");

      }

     

      @EndElement(attributes={@ContainAttribute(value="pt")})

      public void executeInEndElement3(@CurrentBranch String currentBrunch){

            System.out.println(currentBranch);

            System.out.println("Executing something in end element with some attribute with value pt\n");

      }

}

Running a test, passing the above class, like we have done in another examples, system prints:

/beanDescriptor/line/property/
Executing something in end element with attribute mandatory

/beanDescriptor/line/property/
Executing something in end element with some attribute with name mandatory and another with name page and value 4

/beanDescriptor/line/property/
Executing something in end element with some attribute with value pt

/beanDescriptor/line/property2/
Executing something in end element with attribute mandatory

/beanDescriptor/line/property2/
Executing something in end element with some attribute with value pt

As you can see, each method was executed in ending elements that satisfy the conditions. If you want to put more conditions, you need just to put the annotation ContainAttribute with your desired properties. Both attributes from ContainAttribute, name and value, accept regular expression.

If you repair in the result presented above, there are methods executing in same ending element, for example, the element /beanDescriptor/line/property/. It happens, of course, because the element satisfies the conditions of all methods. We didn't tell JColtrane what's the order that we want to make the execution, if more than one method will be executing. Let's supose that you want to execute the method in this order: first executeInEndElement3, after executeInEndElement1 and executeInEndElement2. You want to execute in this order when they will execute in the same "time", in our case, when /beanDescriptor/line/property/ or /beanDescriptor/line/property2/ are ending. Let's make some changes in our class to tell JColtrane the order of execution we want:

public class EndElemetAction {

      @EndElement(priority=2,attributes={@ContainAttribute(name="mandatory")})

      public void executeInEndElement1(@CurrentBranch String currentBranch){

            System.out.println(currentBranch);

            System.out.println("Executing something in end element with attribute mandatory\n");

      }

     

      @EndElement(attributes={@ContainAttribute(name="mandatory"),@ContainAttribute(name="page",value="4")})

      public void executeInEndElement2(@CurrentBranch String currentBranch){

            System.out.println(currentBranch);

            System.out.println("Executing something in end element with some attribute with name mandatory and another with name page and value 4\n");

      }

     

      @EndElement(priority=3,attributes={@ContainAttribute(value="pt")})

      public void executeInEndElement3(@CurrentBranch String currentBranch){

            System.out.println(currentBranch);

            System.out.println("Executing something in end element with some attribute with value pt\n");

      }

}

Executing the test with the changes, we have:

/beanDescriptor/line/property/
Executing something in end element with some attribute with value pt

/beanDescriptor/line/property/
Executing something in end element with attribute mandatory

/beanDescriptor/line/property/
Executing something in end element with some attribute with name mandatory and another with name page and value 4

/beanDescriptor/line/property2/
Executing something in end element with some attribute with value pt

/beanDescriptor/line/property2/
Executing something in end element with attribute mandatory

As you can see, we have exactly the desired result using the property priority. Annoted methods wiht higher priority will be executed before those with lower priority.

JColtrane give to priority the value 0 (zero) by default. This is the reason we didn't give method executeInEndElement2 a priority value and it was executed after another methods.

We summarizes all the option in table bellow:

Option Arguments Meaning
tag regex element must have tag that match with given regular expression
uri regex element must have uri that match with given regular expression
localName regex element must have local name that match with given regular expression
priority int methods with higher priorities will be executed before those with lower priorities
ContainAtribute (name regex, value regex) element must have attribute that matchs with given regular expression name and value

Now that you now the basic options, let's see another ways to refine filtering.