TomWiedenhoeft - 2005-02-24

Hallo, again!

Here are two other classes that might interest you.

Benefit:
Convenient way to read values from an XML file to populate forms for example.

The FindXMLFileTagHandler.java finds XML files.
The GetElementInXMLFileTagHandler.java reads values of XML elements in a file.

Example:
FindXMLFileTagHandler can find files containing an  XML element, for example <ContainerId>MyValue</ContainerId>.
The GetElementInXMLFileTagHandler.java reads the value 'MyValue' in the element <ContainerId>.

There are more explanations and examples in the javadoc of the classes.

If you think the classes are usefull for you or other users please intergrate them into the official version.
We hope this small contibution will help to spread and develop JFC-Unit.

Thanks a lot.
Tom Wiedenhoeft

P.S. Please note to modify the files XMLConstants.java and TagMapping.properties as shown below.

---schnipp  -- FindXMLFileTagHandler.java ---

package junit.extensions.xml.elements;

import junit.extensions.xml.IXMLTestCase;
import junit.extensions.xml.XMLException;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;

import org.jdom.input.SAXBuilder;
import org.jdom.Document;
import org.jdom.JDOMException;
import org.w3c.dom.Element;
import org.apache.regexp.RE;

/**
* This is tag handler finds files in a directory.
* It looks into every file in the directory. The file
* must contain an XML-element with a given name and a
* given value.
* <p>
* <h3>Description</h3>
* <pre>
* id           - Referenz for later usage [required]
* dir          - Directory where file should be found [required]
* xmlElement   - Name of the XML element [required]
* ignoreErrors - The reading of the file might throw errors.
*                The TagHandler can ignore this.
*                If ignored the referenz (id) is null and thats it.
*                If not ignored (default) an error is thrown.
*                (The test will fail.)
*                Q: Where can it be usefull?
*                A: Parallel working robots. Robots might grab the
*                   same file and not only read them (move, change,..)
*                Q: How can I check if an errors did happen?
*                A: Later reference of attribute "id" will be null.
*                Default is "no" [optional]
* value        - Value inside the XML element
*                [required] if "regexp" is not provided
* regexp       - Value inside the XML element as regular expression
*                [required] if "value" is not provided
* </pre>
* <p>
* If both value and regexp are given the TagHandler will take the regexp.
* </p>
* <p>
* The attribute value is a regular expression (api regexp by apache.org).
* </p>
* <p>
* References to the file will be accessible by<br>
* - &quot;id&quot; for the java.io.File. Example &quot;bag&quot;.<br>
* - &quot;id.name&quot; for the name of the file.
*   Example &quot;bag.name&quot; to get &quot;12.xml&quot;.<br>
* - &quot;id.path&quot; for the absolut path.
*   Example &quot;bag.path&quot; to get &quot;c:/tmp/12.xml&quot;.<br>
* - &quot;id.dir&quot; for the directory.
*   Example &quot;bag.dir&quot; to get &quot;c:/tmp&quot;.<br>
* </p>
*
* <h3>Example</h3>
* <p>
* Find a file in direcory &quot;c:/tmp&quot;. The file must
* contain an xml element<br>
* &lt;AA&gt; oktoberfest in munich &lt;AA/&gt;
* </p>
* <pre>
* &lt;findXMLFile
*         id=&quot;myid&quot;
*         dir=&quot;c:/tmp&quot;
*         xmlElement=&quot;AA&quot;
*         ignoreErrors=&quot;yes&quot;
*         value=&quot;oktoberfest in munich&quot;/&gt;
* </pre>
* <pre>
* &lt;findXMLFile
*         id=&quot;myid&quot;
*         dir=&quot;c:/tmp&quot;
*         xmlElement=&quot;AA&quot;
*         regexp=&quot;^oktoberfest in munich$&quot;/&gt;
* </pre>
* <br>
* <h3>A more realistic example</h3>
* <p>
* Below a more realistic example that finds files containing an
* XML element 'ContainerId'. Additionally it reads out the value of
* the XML element 'ContainerId' and echos it to std.out.
* </p>
* <p>
* Content of the sample file living in 'c:/tmp'.
* </p>
* <pre>
* &lt;sampleFile/&gt;
*   &lt;ContainerId/&gt;ABC12345&lt;/ContainerId/&gt;
* &lt;/sampleFile/&gt;
* </pre>
* <p>
* Test that reads out the 'ContainerId' in the sample file and echos it to std.out.
* </p>
* <pre>
* &lt;suite name="Suite"&gt;
* &lt;test name="FindXmlFileExample" robot="true"&gt;
*     &lt;!--  Define the "working" directory of this robot. The robot finds its files there. --&gt;
*     &lt;property name="robotDir" value="c:/tmp"/&gt;
*     &lt;echo message="Files are searched in directory: ${robotDir}" mode="stdout"/&gt;
*
*     &lt;echo message="Looking for files containing an XML element 'ContainerId' with any value in ${robotDir}..." mode="stdout"/&gt;
*     &lt;!-- Parallel working robots might grab the same file at the same time. Ignore those errors. --&gt;
*     &lt;findXMLFile id="bag" dir="${robotDir}" xmlElement="ContainerId" regexp=".*" ignoreErrors="true" /&gt;
*
*     &lt;choose&gt;
*         &lt;when test="assertnotnull" actualrefid="bag"&gt;
*             &lt;echo message="A file '${bag.name}' was found in ${robotDir}." mmode="stdout"/&gt;
*
*             &lt;echo message="Getting the 'ContainerId' in file ${bag.name}..." mode="stdout"/&gt;
*             &lt;!-- Parallel working  robots might grab the same file at the same time. Ignore those errors. --&gt;
*             &lt;getElementInXMLFile file="${robotDir}/${bag.name}" xmlElement="ContainerId" id="wandId" ignoreErrors="true" /&gt;
*             &lt;choose&gt;
*                 &lt;when test="assertnotnull" actualrefid="wandId"&gt;
*                     &lt;echo message="Found the id ${wandId}..." mode="stdout"/&gt;
*                     &lt;!-- Now the robot could use the id to populate a textfield in a GUI like this
*                     &lt;key string="${wandId}" refid="JFrame"/&gt;
*                     --&gt;
*                 &lt;/when&gt;
*             &lt;/choose&gt;
*         &lt;/when&gt;
*     &lt;/choose&gt;
* &lt;/test&gt;
* &lt;/suite&gt;
* </pre>
* @author tom@smart-tail.com (Tom Wiedenhoeft, DV-Ratio acting under contract with Siemens L&A PA)
*/
public class FindXMLFileTagHandler extends AbstractTagHandler {
    /**
     * constructor.
     * @param element Element to be processed.
     * @param testCase containing test case.
     */
    public FindXMLFileTagHandler(final Element element,
        final IXMLTestCase testCase) {
        super(element, testCase);
    }

    /**
     * Get the value of the id attribute.
     * @return String value of the id attribute.
     */
    public String getId() {
        return getString(ID);
    }

    /**
     * Get the directory attribute from the element.
     * @return String The value of the directory attribute.
     */
    public String getDirectory() {
        return getString(DIRECTORY);
    }

    /**
     * Get the value of the xmlElement attribute.
     * @return String value of the xmlElement attribute.
     */
    public String getXMLElement() {
        return getString(XML_ELEMENT);
    }

    /**
     * Get the value of the value attribute.
     * @return String value of the value attribute.
     */
    public String getValue() {
        return getString(VALUE);
    }

    /**
     * Get the value of the regexp attribute.
     * @return String value of the regexp attribute.
     */
    public String getRegexp() {
        return getString(REGEXP);
    }

    /**
     * Get the value of the ignoreErrors attribute.
     * @return String value of the ignoreErrors attribute.
     */
    public String getIgnoreErrors() {
        return getString(IGNORE_ERRORS);
    }

    /**
     * Process the element.
     * Stores an object of type java.io.File for later usage in the cache.
     * This object is later accessable via the "id".
     * @throws XMLException may be thrown.
     */
    public void processElement() throws XMLException {
        validateElement();
        // Get the attribute value
        String id = this.getId();

        // Get the file
        File file = this.getFile();

        String name = null;
        String path = null;
        String dir = null;
        if(file != null)
        {
            name = file.getName();
            path = file.getAbsolutePath();
            dir = file.getParent().toString();
        }
        // Store the file
        getXMLTestCase().addProperty(id, file);
        getXMLTestCase().addProperty(id + "." + NAME, name);
        getXMLTestCase().addProperty(id + "." + ABSOLUTE_PATH, path);
        getXMLTestCase().addProperty(id + "." + DIRECTORY, dir);
    }

    /**
     * Validate that the element is properly configured.
     * @throws XMLException Exception may be thrown if there
     * are missing elements.
     */
    public void validateElement() throws XMLException {
        // check the element tag name
        checkElementTagName(FIND_XML_FILE);

        checkRequiredAttribute(ID);

        checkRequiredAttribute(DIRECTORY);

        checkRequiredAttribute(XML_ELEMENT);

        // Either value or regexp must be given
        String value = this.getValue();
        String regexp = this.getRegexp();
        if(value == null && regexp == null)
        {
            throw new XMLException("Attribute 'value' or 'regexp' are mandatory.",
                    null,
                    getElement(),
                    getTest().getPropertyCache());
        }
    }

    /**
     * Iterate through a list of files found in the directory.
     * Find the given XML element. Get the value of the XML element
     * Compare its value against the given value.
     * value. The value must match a regular expression or string
     * (see the documentation of the class).
     *
     * @return java.io.File where a matching element was found.
     * @throws XMLException
     */
    private File getFile() throws XMLException
    {
        // Get the attribute values
        String dir = this.getDirectory();
        String elementName = this.getXMLElement();

        // In case more than one robot work on the same file.
        // Thats the purpose of boolean ignore
        String ignoreErrors = this.getIgnoreErrors();
        boolean ignore = false;
        if(ignoreErrors != null && ! "".equals(ignoreErrors))
        {
            if(ignoreErrors.trim().equalsIgnoreCase("yes"))
            {
                ignore = true;;
            }
            if(ignoreErrors.trim().equalsIgnoreCase("true"))
            {
                ignore = true;;
            }
        }

        // Get a file in the directory and check the directory
        File directory = new File(dir);
        if(! directory.exists())
        {
            throw new XMLException("Directory does not exist: " + dir,
                null,
                getElement(),
                getTest().getPropertyCache());
        }
        if(! directory.isDirectory())
        {
            throw new XMLException(dir + " is not a directory.",
                null,
                getElement(),
                getTest().getPropertyCache());
        }

        // Iterate through all files in the directory
        File[] files = directory.listFiles();
        for(int i = 0; i < files.length; i++)
        {
            File file = files[i];
            if(! file.isFile())
            {
                // We are not interested in directories
                continue;
            }
            // Create a URL for the file. (Used by SAX Builder)
            String fileString = file.getAbsolutePath();
            fileString = "file:" + fileString;
            URL url = null;
            try {
                url = new URL(fileString);
            } catch(MalformedURLException e) {
                throw new XMLException(fileString + " is a malformed URL.",
                    null,
                    getElement(),
                    getTest().getPropertyCache());
            }

            // Look into the file. Let the SAX builder create an
            // XML document.
            SAXBuilder builder = new SAXBuilder();
            Document doc = null;
            try {
                doc = builder.build(url);
            } catch(JDOMException e) {
                if(ignore)
                {
                    System.err.println("The TagHandler will IGNORE the above EXCEPTION");
                    System.err.println(
                            "An Exception was thrown inside FindXMLFileTagHandler"
                            + "while reading the XML file. Exception message is: "
                            + e.getMessage());
                    return null;
                }
                else
                {
                    e.printStackTrace();
                    throw new XMLException(
                            "Error with file " + this.getFile() + ". " + e.getMessage(),
                            null,
                            getElement(),
                            getTest().getPropertyCache());
                }
            }
            org.jdom.Element root = doc.getRootElement();
            // Check wether children do exist
            // Check wether the XML element (with a certain name) does exist
            // for example <AA>
            org.jdom.Element child = root.getChild(elementName);
            if(child != null)
            {
                String desc = child.getTextTrim();
                if(desc != null)
                {
                    // Compare the value of the XML element
                    // Example: <AA>myvalue</AA>
                    String regexp = this.getRegexp();
                    String value = this.getValue();
                    if(regexp != null)
                    {
                        // The value "myvalue" must match a reg. expression
                        RE re = new RE(regexp);
                        boolean isMatching = re.match(desc);
                        if(isMatching)
                        {
                            // Yes, the file contains an XML element
                            // with a certain value. Example: AA>myvalue</AA>
                            return file;
                        }
                    }
                    else if(value != null)
                    {
                        if(value.equals(desc))
                        {
                            // Yes, the file contains an XML element
                            // with a certain value. Example: AA>myvalue</AA>
                            return file;
                        }
                    }
                }
            }
        }
        return null;
    }
}

---schnapp -- FindXMLFileTagHandler.java ---

---schnipp  -- FindXMLFileTagHandler.java ---

package junit.extensions.xml.elements;

import junit.extensions.xml.IXMLTestCase;
import junit.extensions.xml.XMLException;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import org.jdom.input.SAXBuilder;
import org.jdom.Document;
import org.jdom.JDOMException;

import org.w3c.dom.Element;

/**
* This is tag handler gets a value of an XML element in a file.
*
* <h3>Description</h3>
* <pre>
* id           - Referenz to the found value of XML element [required]
* xmlElement   - Name of the XML element [required]
* ignoreErrors - The reading of the file might throw errors.
*                The TagHandler can ignore this.
*                If ignored the referenz (id) is null and thats it.
*                If not ignored (default) an error is thrown.
*                (The test will fail.)
*                Default is "no" [optional]
*                Remark: A not existing file will throw an error.
*                Where can it be usefull? Imagine parallel working
*                robots trying to read the same files at the same
*                time. Reading is ok. But if file manipulation
*                is involved (like moving files) errors are likely
*                to occure.
* file         - Filename inluding absolute path to file.
*                [required]
* </pre>
* <p>
* References to the found value of &quot;AA&quot; will later be accessible by
* the property &quot;id&quot; .<br>
*   Example: &quot;party&quot; will deliver &quot;oktoberfest in munich&quot;,
*   see example below.
* </p>
* <h3>Example</h3>
* <p>
* Read the value of the xml element
* &lt;AA&gt; oktoberfest in munich &lt;AA/&gt;
* in the file &quot;c:/tmp/12.xml&quot;
* </p>
* <pre>
* &lt;getElementInXMLFile
*         file=&quot;c:/tmp/12.xml&quot;
*         xmlElement=&quot;AA&quot;
*         ignoreErrors=&quot;no&quot;
*         id=&quot;party&quot;/&gt;
* </pre>
* @author tom@smart-tail.com (Tom Wiedenhoeft, DV-Ratio acting under contract with Siemens L&A PA)
*/
public class GetElementInXMLFileTagHandler extends AbstractTagHandler {
    /**
     * constructor.
     * @param element Element to be processed.
     * @param testCase containing test case.
     */
    public GetElementInXMLFileTagHandler(final Element element,
        final IXMLTestCase testCase) {
        super(element, testCase);
    }

    /**
     * Get the value of the id attribute.
     * @return String value of the id attribute.
     */
    public String getId() {
        return getString(ID);
    }

    /**
     * Get the file attribute from the element.
     * @return String The value of the refid attribute.
     */
    public String getFile() {
        return getString(FILE);
    }

    /**
     * Get the value of the xmlElement attribute.
     * @return String value of the xmlElement attribute.
     */
    public String getXMLElement() {
        return getString(XML_ELEMENT);
    }

    /**
     * Get the value of the ignoreErrors attribute.
     * @return String value of the ignoreErrors attribute.
     */
    public String getIgnoreErrors() {
        return getString(IGNORE_ERRORS);
    }

    /**
     * Process the element.
     * Stores an object of type String for later usage in the cache.
     * This object is later accessable via the "id".
     * @throws XMLException may be thrown.
     */
    public void processElement() throws XMLException {
        validateElement();
        // Get the attribute value
        String id = this.getId();

        // Get the content of the XML element
        String elementText = this.getContentOfXMLElement();

        // Store the file
        getXMLTestCase().addProperty(id, elementText);
    }

    /**
     * Validate that the element is properly configured.
     * @throws XMLException Exception may be thrown if there
     * are missing elements.
     */
    public void validateElement() throws XMLException {
        // check the element tag name
        checkElementTagName(GET_ELEMENT_XML_FILE);

        // the element name is a required attribute
        checkRequiredAttribute(XML_ELEMENT);

        // id is a required attribute
        checkRequiredAttribute(ID);

        // file is a required attribute
        checkRequiredAttribute(FILE);
    }

    /**
     * Iterate through a list of files found in the directory.
     * Find the given element. Compare its value against the given
     * value.
     *
     * @return Content of XML element as String.
     * @throws XMLException
     */
    private String getContentOfXMLElement() throws XMLException
    {
        // Get the attribute values
        String f = this.getFile();
        String elementName = this.getXMLElement();
        String ignoreErrors = this.getIgnoreErrors();

        // In case more than one robot work on the same file.
        // Thats the purpose of boolean ignore
        boolean ignore = false;
        if(ignoreErrors != null && ! "".equals(ignoreErrors))
        {
            if(ignoreErrors.trim().equalsIgnoreCase("yes"))
            {
                ignore = true;;
            }
            if(ignoreErrors.trim().equalsIgnoreCase("true"))
            {
                ignore = true;;
            }
        }

        // Get the stored file
        File file = new File(f);

        // Check the file
        if(! file.exists())
        {
            throw new XMLException("File does not exist: " + f,
                null,
                getElement(),
                getTest().getPropertyCache());
        }
        if(! file.isFile())
        {
            throw new XMLException(f + " is not a file.",
                null,
                getElement(),
                getTest().getPropertyCache());
        }

        // Create a URL for the file. (Used by SAX Builder)
        String fileString = "file:" + file;
        URL url = null;
        try {
            url = new URL(fileString);
        } catch(MalformedURLException e) {
            throw new XMLException(fileString + " is a malformed URL.",
                null,
                getElement(),
                getTest().getPropertyCache());
        }

        // Look into the file. Let the SAX builder create an
        // XML document.
        SAXBuilder builder = new SAXBuilder();
        Document doc = null;
        try {
            doc = builder.build(url);
        } catch(JDOMException e) {
            if(ignore)
            {
                System.err.println("The TagHandler will IGNORE the above EXCEPTION");
                System.err.println(
                        "An Exception was throw inside GetElementInXMLFileTagHandler"
                        + "while reading the XML file. Exception message is: "
                        + e.getMessage());
                return null;
            }
            else
            {
                e.printStackTrace();
                throw new XMLException(
                        "Error with file " + this.getFile() + ". " + e.getMessage(),
                        null,
                        getElement(),
                        getTest().getPropertyCache());
            }
        }
        org.jdom.Element root = doc.getRootElement();

        // Check wether the element does exist
        org.jdom.Element child = root.getChild(elementName);
        String elementContent = null;
        if(child != null)
        {
            // Get the content of the xml element
            elementContent = child.getTextTrim();
        }
        return elementContent;
    }
}

---schnapp -- FindXMLFileTagHandler.java ---

Please add in TagMapping.properties

---schnipp -- TagMapping.properties ---
findXMLFile = junit.extensions.xml.elements.FindXMLFileTagHandler
getElementInXMLFile = junit.extensions.xml.elements.GetElementInXMLFileTagHandler
---schnapp -- TagMapping.properties ---

Please add in XMLConstants.java

---schnipp -- XMLConstants.java ---
    /** directory. */
    String DIRECTORY = "dir";
    /** xml element (in file). */
    String XML_ELEMENT = "xmlElement";
    /** regexp */
    String REGEXP = "regexp";
    /** ignoreErrors */
    String IGNORE_ERRORS = "ignoreErrors";
    /** getElementInXMLFile taghandler. */
    String GET_ELEMENT_XML_FILE = "getElementInXMLFile";
    /** findXMLFile taghandler. */
    String FIND_XML_FILE = "findXMLFile";
    /** path. */
    String ABSOLUTE_PATH = "path";
---schnapp -- XMLConstants.java ---