Starting this May, mortgage folk are going to be required to send Freddie and Fannie data including additional data points in ULDD phase 3 extension. At face value, adding these additional data points shouldn’t be a big deal at all. However, the legacy code I’m maintaining used XML::Compile to generate code. For various and sondry reasons — which I will not go into here — XML::Compile in the code I’m maintaining was in a place where it was extremely difficult to add XML elements that weren’t included in the original base Mismo 3.0 namespace.
If you, too, are stuck with a Perl hash structure marshalled into XML by XML::Compile and need to add elements in an extension namespace, I have good new for you. Using LibXML you can manually insert XML nodes from the extension namespace into your Perl hash object and XML::Compile will correctly marshall the structure into valid XML.
use warnings;
use strict;
#...
use XML::Compile::Schema;
use XML::Compile::Util qw/pack_type/;
use XML::LibXML;
use File::Slurp;
my @specs = ('MISMO_3_0.xsd', 'xlink.xsd', 'ULDD_Phase_3_Extension.xsd');
my $schema = XML::Compile::Schema->new( \@specs, ( element_form_default => 'qualified' ) );
my $writer = $schema->compile( WRITER => pack_type( 'http://www.mismo.org/residential/2009/schemas', 'MESSAGE' ), use_default_namespace => 0 );
my $uldd_other = create_xml_node("OTHER");
my $uldd_loan_identifier_extension = create_xml_node("LOAN_IDENTIFIER_EXTENSION");
my $uldd_loanidentifier = create_xml_element($d, "LoanIdentifier");
my $uldd_loanidentifiertype = create_xml_element($d, "LoanIdentifierType");
$uldd_loan_identifier_extension->appendChild($uldd_loanidentifier);
$uldd_loan_identifier_extension->appendChild($uldd_loanidentifiertype);
$uldd_other->appendChild($uldd_loan_identifier_extension);
my $xml_data = {
#...
LOAN_IDENTIFIERS => {
LOAN_IDENTIFIER => [
#...
{EXTENSION => {
pack_type('http://www.datamodelextension.org/Schema/ULDD', 'OTHER') => $uldd_other,
},},
],
},
#...
};
my $doc = XML::LibXML::Document->new( '1.0', 'UTF-8' );
my $xml = $writer->( $doc, $xml_data );
$xml->setAttribute('xmlns:ULDD', 'http://www.datamodelextension.org/Schema/ULDD');
$doc->setDocumentElement($xml);
$xml = $doc->toString(1);
write_file( $filename, $xml );
sub create_xml_node {
my ( $node_name ) = @_;
my $node = XML::LibXML::Element->new($node_name);
$node->setNamespace("http://www.datamodelextension.org/Schema/ULDD", "ULDD");
return $node;
}
sub create_xml_element {
my ( $d, $node_name ) = @_;
my $node = XML::LibXML::Element->new($node_name);
$node->setNamespace("http://www.datamodelextension.org/Schema/ULDD", "ULDD");
if (exists($d->{$node_name}) && defined($d->{$node_name})) {
$node->appendText($d->{$node_name});
return $node;
}
return undef;
}
As you can see, this isn’t all too complicated. You use pack_type
to let XML::Compile know about the extension namespace and then you basically build your own XML strucuture using LibXML.