XML Exports with a Little Help from Java

Java & XML

The other day I was working on a new export for Blackboard Connect when I ran into a common problem: of the fourteen fields I needed to export, one of them had special logic that couldn’t be handled via the XML definition. Ugh! That meant I was going to have to convert the entire export to Java. Or so I thought until a little lightbulb went off. Read on to learn how you can use this tip to save yourself from writing an entire export with Java.

Here’s the Blackboard Connect export I created in XML:

<!-- ************************************************ -->
<!-- Definition for Blackboard Connect Student export -->
<!-- ************************************************ -->
<export table-id="tblStudent" header-row="true" line-separator="windows">

 <filter field="stdEnrStatus"              operator="equals"   value= "Active" />
 <filter field="relStdSklOid.sklSchoolID"  operator="notEqual" value= "Salmond" />
 <filter field="relStdSklOid.sklSchoolID"  operator="notEqual" value= "District" />
 <filter field="relStdSklOid.sklSchoolID"  operator="notEqual" value= "Outside" />
 <filter field="relStdSklOid.sklSchoolID"  operator="notEqual" value= "Extended" />
 <filter field="relStdSklOid.sklSchoolID"  operator="notEqual" value= "Committee" />
 <filter field="relStdSklOid.sklFieldA003" operator="notEmpty" />

 <sort field="stdViewName" direction="asc" />

 <field id="stdIDState"                 header-source="constant" header-value="ReferenceCode" />
 <field id="relStdPsnOid.psnNameFirst"  header-source="constant" header-value="FirstName" />
 <field id="relStdPsnOid.psnNameLast"   header-source="constant" header-value="LastName" />
 <field id="stdGradeLevel"              header-source="constant" header-value="Grade" />
 <field id="relStdPsnOid.psnGenderCode" header-source="constant" header-value="Gender" />
 <field id="relStdPsnOid.psnPhone01"    header-source="constant" header-value="HomePhone" />
 <field id="relStdPsnOid.psnPhone02"    header-source="constant" header-value="WorkPhone" />
 <field id="relStdPsnOid.psnPhone03"    header-source="constant" header-value="MobilePhone" />
 <field id="relStdPsnOid.psnEmail01"    header-source="constant" header-value="EmailAddress" />
 <field id="relStdPsnOid.psnEmail02"    header-source="constant" header-value="EmailAddressAlt" />
 <field id="relStdSklOid.sklSchoolName" header-source="constant" header-value="Institution"/>

 <!-- ===================================================== -->
 <!-- This field requires logic to export either "Y" or "N" -->
 <!-- ===================================================== -->
 <field id="stdFieldB044" header-source="constant" header-value="Group"/> 

 <constant value="Student" header-value="ContactType"/>
 <blank header-value="Terminate"/>
</export>

As you can see, the export covers all bases: filters, sorts, fields, constants, blanks. The problem arose with the <field> for stdFieldB044 (line 31). This field represents Massachusetts SIMS 36 (Data Dictionary alias DOE 36), Special Education Primary Disability. Our district is using that field to determine if a student is in Special Education and should either export the letter Y if so or the letter N if not. The logic for that test is this: if the field’s value is empty or it matches “Does Not Apply (500)” then export N otherwise export Y.

The only way to implement logic like that in an export is with Java code. Back to my original statement: Ugh! Those 35 lines of XML markup would require potentially hundreds of lines of Java code. Normally when you create a Java-based export, your Java class extends a class called ExportJavaSource but if we instead extend XmlDefinitionExport then we can save ourselves lots of code. XmlDefinitionExport is designed to process an XML-based export (hence the name!) and we’re just going to inject a tiny bit of code to override how field stdFieldB044 will be processed. Let’s look at the code to put it in perspective:

import java.util.Map;

import com.follett.fsc.core.k12.beans.X2BaseBean;
import com.follett.fsc.core.k12.tools.exports.XmlDefinitionExport;
import com.x2dev.utils.X2BaseException;
import com.x2dev.utils.StringUtils;

/**
 * Java source for XML-based exports that need some extra help formatting one or more fields.
 *
 * @author Brian Ciccolo
 */
public class XmlWithHelpExport extends XmlDefinitionExport
{
    /**
     * Applies custom formatting to field "DOE 36" (stdFieldB044). All other fields are processed
     * normally.
     */
    protected String getPropertyValue(X2BaseBean bean, 
                                      Object property, 
                                      Map<String, Object> attributes)
        throws X2BaseException
    {
        String value = super.getPropertyValue(bean, property, attributes);

        if (property != null && property.equals("stdFieldB044"))
        {
            if (StringUtils.isEmpty(value) || value.equalsIgnoreCase("Does Not Apply (500)"))
            {
                value = "N";
            }
            else
            {
                value = "Y";
            }
        }
        
        return value;
    }
}

My Java class only needs to implement the getPropertyValue() method. This method is called once for every property defined in my XML for each record in the import. It’s a great method and I’m happy to let it do it’s thing. I do that by calling super.getPropertyValue() (line 24). Then, if the method is being called for my property – stdFieldB004 – I inject my custom logic (lines 26 – 36). And that’s it! The export works great with this combination of XML (93% of the work) and Java (7% of the work).

You can use this Java class to provide some help to your own XML exports. Simply customize lines 26 – 36 to meet the needs for your specific property. You can even add logic for additional properties if there are multiple fields you need to adjust.

One point to make is that your XML can use an alias but by the time the getPropertyValue() is called it will be converted to a Data Dictionary Field OID. So if my XML above included this version of line 31 instead:

<field id="DOE 36" type="alias" header-source="constant" header-value="Group"/>

The code in super.getPropertyValue() still needs to check for:

property.equals("stdFieldB044")

Let me know in the comments if you’ve run into situations where you used (or could have used) this tip.

3 thoughts on “XML Exports with a Little Help from Java

  1. kcadieux

    Thanks for this, Brian! I used it to convert low income (DOE 19) data to a number so we could feed it to our online payment system and give certain students discounts on their school activities. So helpful!

  2. kcadieux

    Hi Brian, can you help me?

    I have a translation for gender in my export, but I want to add another for stdGradeLevel if KT, KP, or KF to K.

    – 1st: I’m not sure of the placement in the source code. When I compile, I get this error: /usr/fsc/tomcat/webapps/aspen/temp/x2_3746404768301063319/x2_8657025982191317913/XmlWithHelpExport.java:38: error: unreachable statement
    if (property != null && property.equals(“stdGradeLevel”))
    ^
    1 error

    -2nd: and not as important, how do I structure it to have OR instead of having three different IFs like this:

    if (property != null && property.equals(“stdGradeLevel”))

    if (value.equalsIgnoreCase(“KP”))
    {
    value = “K”;
    }
    if (value.equalsIgnoreCase(“KF”))
    {
    value = “K”;
    }
    if (value.equalsIgnoreCase(“KT”))
    {
    value = “K”;
    }
    return value;

    Here’s the source code without the grade translation:
    import java.util.Map;

    import com.follett.fsc.core.k12.beans.X2BaseBean;
    import com.follett.fsc.core.k12.tools.exports.XmlDefinitionExport;
    import com.x2dev.utils.X2BaseException;
    import com.x2dev.utils.StringUtils;

    /**
    * Java source for XML-based exports that need some extra help formatting one or more fields.
    *
    *
    */
    public class XmlWithHelpExport extends XmlDefinitionExport
    {
    /**
    * Applies custom formatting to field “relStdPsnOid.psnGenderCode” All other fields are processed
    * normally.
    */
    protected String getPropertyValue(X2BaseBean bean,
    Object property,
    Map attributes)
    throws X2BaseException
    {
    String value = super.getPropertyValue(bean, property, attributes);

    if (property != null && property.equals(“relStdPsnOid.psnGenderCode”))

    if (value.equalsIgnoreCase(“M”))
    {
    value = “2”;
    }
    if (value.equalsIgnoreCase(“F”))
    {
    value = “1”;
    }
    return value;
    }
    }

    Thanks!!

Leave a Reply