Skip to content

Commit 9d807bb

Browse files
author
André L F S Bacci
committed
XInclude by xml:id
1 parent 5614457 commit 9d807bb

File tree

1 file changed

+105
-27
lines changed

1 file changed

+105
-27
lines changed

configure.php

Lines changed: 105 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -774,47 +774,108 @@ function getFileModificationHistory(): array {
774774
}
775775
echo "done.\n";
776776

777-
echo "Running XInclude/XPointer... ";
778-
$total = 0;
779-
$maxrun = 10; //LIBXML_VERSION >= 21100 ? 1 : 10;
780-
for( $run = 0 ; $run < $maxrun ; $run++ )
777+
echo "Running XInclude... ";
778+
779+
$total = xinclude_run_byid( $dom );
780+
$total += xinclude_run_xpointer( $dom );
781+
782+
if ( $total == 0 )
783+
echo "failed.\n";
784+
else
785+
echo "done. Performed $total XIncludes.\n";
786+
787+
xinclude_report();
788+
xinclude_residual( $dom );
789+
790+
function xinclude_run_byid( DOMDocument $dom )
781791
{
782-
if ( $run > 0 )
783-
echo "$run ";
784-
libxml_clear_errors();
785-
$status = (int) $dom->xinclude();
786-
if ( $status <= 0 )
787-
break;
788-
$total += $status;
789-
if ( $maxrun > 1 && $run + 1 >= $maxrun )
792+
$total = 0;
793+
$maxrun = 10; //LIBXML_VERSION >= 21100 ? 1 : 10;
794+
for( $run = 0 ; $run < $maxrun ; $run++ )
790795
{
791-
echo "Recursive XInclude is too deep.\n";
792-
errors_are_bad(-1);
796+
$xpath = new DOMXPath( $dom );
797+
$xpath->registerNamespace( "xi" , "http://www.w3.org/2001/XInclude" );
798+
$xincludes = $xpath->query( "//xi:include" );
799+
800+
$progress = false;
801+
foreach( $xincludes as $xinclude )
802+
{
803+
$xpointer = $xinclude->getAttribute( "xpointer" );
804+
$target = $xinclude->ownerDocument->getElementById( $xpointer );
805+
806+
if ( $target == null )
807+
continue;
808+
809+
$other = new DOMDocument( '1.0' , 'utf8' );
810+
$frags = $other->createDocumentFragment();
811+
$other->append( $frags );
812+
$frags->append( $other->importNode( $target , true ) ); // dup add
813+
814+
// "attributes in xml: namespace are not copied"
815+
816+
$oxpth = new DOMXPath( $other );
817+
$attribs = $oxpth->query( "//@*" );
818+
819+
foreach( $attribs as $attrib )
820+
if ( $attrib->prefix == "xml" )
821+
$attrib->parentNode->removeAttribute( $attrib->nodeName );
822+
823+
$insert = $dom->importNode( $frags , true ); // dup
824+
$xinclude->parentNode->insertBefore( $insert , $xinclude ); // add
825+
$xinclude->parentNode->removeChild( $xinclude ); // del
826+
827+
$progress = true;
828+
$total++;
829+
}
830+
831+
if ( $progress )
832+
continue;
833+
else
834+
return $total;
793835
}
836+
echo "XInclude nested too deeply (xml:id).\n";
837+
errors_are_bad( -1 );
794838
}
795839

796-
if ($total == 0) {
797-
echo "failed.\n";
798-
} else {
799-
echo "done. Performed $total XIncludes.\n";
840+
function xinclude_run_xpointer( DOMDocument $dom ) : int
841+
{
842+
$total = 0;
843+
$maxrun = 10; //LIBXML_VERSION >= 21100 ? 1 : 10;
844+
for( $run = 0 ; $run < $maxrun ; $run++ )
845+
{
846+
echo ".";
847+
libxml_clear_errors();
848+
$status = (int) $dom->xinclude();
849+
if ( $status <= 0 )
850+
return $total;
851+
$total += $status;
852+
}
853+
echo "XInclude nested too deeply (xpointer).\n";
854+
errors_are_bad( -1 );
800855
}
801-
flush();
802856

803-
if ( $ac['XPOINTER_REPORTING'] == 'yes' || $ac['LANG'] == 'en' )
857+
function xinclude_report()
804858
{
859+
global $ac;
860+
861+
$report = $ac['XPOINTER_REPORTING'] == 'yes' || $ac['LANG'] == 'en';
862+
$output = $ac['STDERR_TO_STDOUT'] == 'yes' ? STDOUT : STDERR;
863+
$fatal = $ac['LANG'] == 'en';
864+
805865
$errors = libxml_get_errors();
806-
$output = ( $ac['STDERR_TO_STDOUT'] == 'yes' ) ? STDOUT : STDERR;
807-
if ( count( $errors ) > 0 )
866+
libxml_clear_errors();
867+
868+
if ( count( $errors ) > 0 && $report )
808869
{
809-
fprintf( $output , "\n");
870+
fprintf( $output , "\n\n");
810871
foreach( $errors as $error )
811-
fprintf( $output , "{$error->message}\n");
812-
if ( $ac['LANG'] == 'en' )
813-
errors_are_bad(1);
872+
fprintf( $output , rtrim( $error->message ) . "\n\n" );
873+
if ( $fatal )
874+
errors_are_bad( 1 );
814875
}
815876
}
816877

817-
if ( $ac['LANG'] != 'en' )
878+
function xinclude_residual( DOMDocument $dom )
818879
{
819880
// XInclude failures are soft errors on translations, so remove
820881
// residual XInclude tags on translations to keep them building.
@@ -869,6 +930,23 @@ function getFileModificationHistory(): array {
869930
MSG;
870931
exit(-1); // stop here, do not let more messages further confuse the matter
871932
}
933+
934+
// XInclude by xml:id never duplicates xml:id, horever, also using
935+
// XInclude by XPath/XPointer may start causing duplications.
936+
// Crude and ugly fixup ahead, beware!
937+
938+
$list = array();
939+
$nodes = $xpath->query( "//*[@xml:id]" );
940+
foreach( $nodes as $node )
941+
{
942+
$id = $node->getAttribute( "xml:id" );
943+
if ( isset( $list[ $id ] ) )
944+
{
945+
echo " Random removing duplicated xml:id: $id\n";
946+
$node->removeAttribute( "xml:id" );
947+
}
948+
$list[ $id ] = $id;
949+
}
872950
}
873951

874952
echo "Validating {$ac["INPUT_FILENAME"]}... ";

0 commit comments

Comments
 (0)