[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[EP-tech] <epc:list>
- Subject: [EP-tech] <epc:list>
- From: cjg at ecs.soton.ac.uk (Christopher Gutteridge)
- Date: Tue, 6 Feb 2018 22:43:22 +0000
So, today I've been refactoring our citation file as it was a mess. I
split it into one citation per type and made some more citation files
for the more complex fields.
That worked really well, but there was still an issue that lots of cases
needed me to render a comma separated list of fields where some of them
may not be set but you don't want to have "Thing 1, , , Thing 4.".
Doubled up commas are hard to avoid.
So, I wrote a handy new feature. This works like this:
?<epc:list join=", " suffix=".">
??? <epc:item><epc:if test="thing_a"><epc:print expr="thing_a"
/></epc:if></epc:item>
??? <epc:item><epc:if test="thing_b"><epc:print expr="thing_b"
/></epc:if></epc:item>
??? <epc:item><epc:if test="thing_c"><epc:print expr="thing_c"
/></epc:if></epc:item>
??? <epc:item><epc:if test="thing_d"><epc:print expr="thing_d"
/></epc:if></epc:item>
</epc:list>
This will render each list item and only keep it if it contains
characters other than whitespace and tags. so "<span> </span>" will be
skipped but "Foo" will be included.
It uses the? join text to join each non-empty list item and if there are
one or more non-empty items, it puts the suffix and prefix text at the
start and end. You can also use first-join and last-join to use
different link text between the first or last pair.
This feature can be added to current EPrints by overriding a subroutine.
It's brutal, but works. It may require review after a major upgrade. (or
maybe someone will add the feature to the next release!)
This is new and not very tested code, so at your own risk etc.
{
no warnings 'redefine';
*EPrints::XML::EPC::process = sub {
my( $node, %params ) = @_;
if( !defined $node )
{
EPrints::abort( "no node passed to epc process" );
}
# cjg - Potential bug if: <ifset a><ifset b></></> and ifset a is disposed
# then ifset: b is processed it will crash.
if( EPrints::XML::is_dom( $node, "Element" ) )
{
my $name = $node->tagName;
$name =~ s/^epc://;
return $params{session}->xml->create_document_fragment
if $node->hasAttribute( "disabled" ) && $node->getAttribute( "disabled" );
if( $name=~m/^(if|comment|choose|print|debug|phrase|pin|foreach|set|list)$/ )
{
my $fn = "EPrints::XML::EPC::_process_$name";
no strict "refs";
my $r = eval { &{$fn}( $node, %params ); };
use strict "refs";
if( $@ )
{
$params{session}->log( "EPScript error: $@" );
return $params{session}->html_phrase( "XML/EPC:script_error" );
}
return $r;
}
}
my $collapsed = $params{session}->clone_for_me( $node );
my $attrs = $collapsed->attributes;
if( defined $attrs )
{
for( my $i = 0; $i<$attrs->length; ++$i )
{
my $attr = $attrs->item( $i );
my $v = $attr->nodeValue;
my $name = $attr->nodeName;
my $newv = eval { EPrints::XML::EPC::expand_attribute( $v, $name, \%params ); };
if( $@ )
{
$params{session}->log( "EPScript error: $@" );
$newv = $params{session}->phrase( "XML/EPC:script_error" );
}
if( $v ne $newv ) { $attr->setValue( $newv ); }
}
}
if( $node->hasChildNodes )
{
$collapsed->appendChild( EPrints::XML::EPC::process_child_nodes( $node, %params ) );
}
return $collapsed;
}
} # end of block that disabled 'redefine' warnings
sub EPrints::XML::EPC::_process_list
{
my( $node, %params ) = @_;
# if there's only 2 items and first & last join are defined then last join is used.
my $opts = {};
foreach my $atr ( qw/ join suffix prefix first-join last-join / )
{
if( $node->hasAttribute( $atr ) )
{
$opts->{$atr} = $node->getAttribute( $atr );
}
}
my @out_nodes = ();
foreach my $child ( $node->getChildNodes )
{
next unless( EPrints::XML::is_dom( $child, "Element" ) );
my $name = $child->tagName;
$name=~s/^ep://;
$name=~s/^epc://;
if( ! $name eq "item" )
{
EPrints::abort( "In ".$params{in}.": only epc:item is allowed in epc:list.\n".substr( $child->toString, 0, 100 ) );
}
my $collapsed_item = EPrints::XML::EPC::process_child_nodes( $child, %params );
# Add result to the output list IF it's not just whitespace
my $text = $params{session}->xml->to_string( $collapsed_item );
$text =~ s/\s//g;
if( $text ne "" )
{
push @out_nodes, $collapsed_item;
}
}
my $result = $params{session}->make_doc_fragment;
if( scalar @out_nodes > 0 )
{
# at least one item!
if( defined $opts->{prefix} )
{
$result->appendChild( $params{session}->make_text( $opts->{prefix} ) );
}
for( my $pos=0; $pos < scalar @out_nodes; ++$pos )
{
my $join;
if( $pos > 0 ) {
$join = $opts->{join};
if( $pos == 1 && defined $opts->{"first-join"} ) { $join = $opts->{"first-join"}; }
if( $pos == ((scalar @out_nodes)-1) && defined $opts->{"last-join"} ) { $join = $opts->{"last-join"}; }
}
if( defined $join )
{
$result->appendChild( $params{session}->make_text( $join ) );
}
$result->appendChild( $out_nodes[$pos] );
}
if( defined $opts->{suffix} )
{
$result->appendChild( $params{session}->make_text( $opts->{suffix} ) );
}
}
return $result;
}
--
Christopher Gutteridge -- http://users.ecs.soton.ac.uk/cjg
University of Southampton Open Data Service: http://data.southampton.ac.uk/
You should read our Web & Data Innovation blog: http://blogs.ecs.soton.ac.uk/webteam/