1616 | Authors: Dave Barr <[email protected] > | 1717 | Hannes Magnusson <[email protected] > | 1818 | Gwynne Raskind <[email protected] > | 19+ | André L F S Bacci <[email protected] > | 1920 +----------------------------------------------------------------------+
2021*/
2122
@@ -803,46 +804,140 @@ function dom_saveload( DOMDocument $dom , string $filename = "" )
803804
804805
805806echo "Running XInclude/XPointer... " ;
806- $ total = 0 ;
807- $ maxrun = 10 ; //LIBXML_VERSION >= 21100 ? 1 : 10;
808- for ( $ run = 0 ; $ run < $ maxrun ; $ run ++ )
807+
808+ $ total = xinclude_run_byid ( $ dom );
809+ $ total += xinclude_run_xpointer ( $ dom );
810+
811+ if ( $ total == 0 )
812+ echo "failed. \n" ;
813+ else
814+ echo "done. Performed $ total XIncludes. \n" ;
815+
816+ xinclude_report ();
817+ xinclude_residual ( $ dom );
818+
819+ function xinclude_run_byid ( DOMDocument $ dom )
809820{
810- if ( $ run > 0 )
811- echo "$ run " ;
812- libxml_clear_errors ();
813- $ status = (int ) $ dom ->xinclude ();
814- if ( $ status <= 0 )
815- break ;
816- $ total += $ status ;
817- if ( $ maxrun > 1 && $ run + 1 >= $ maxrun )
821+ $ total = 0 ;
822+ $ maxrun = 10 ; //LIBXML_VERSION >= 21100 ? 1 : 10;
823+ for ( $ run = 0 ; $ run < $ maxrun ; $ run ++ )
818824 {
819- echo "Recursive XInclude is too deep. \n" ;
820- errors_are_bad (-1 );
825+ echo "$ run " ;
826+ $ xpath = new DOMXPath ( $ dom );
827+ $ xpath ->registerNamespace ( "xi " , "http://www.w3.org/2001/XInclude " );
828+ $ xincludes = $ xpath ->query ( "//xi:include " );
829+
830+ $ changed = false ;
831+ foreach ( $ xincludes as $ xinclude )
832+ {
833+ $ xpointer = $ xinclude ->getAttribute ( "xpointer " );
834+ $ target = $ xinclude ->ownerDocument ->getElementById ( $ xpointer );
835+
836+ if ( $ target == null )
837+ continue ;
838+
839+ $ other = new DOMDocument ( '1.0 ' , 'utf8 ' );
840+ $ frags = $ other ->createDocumentFragment ();
841+ $ other ->append ( $ frags );
842+ $ frags ->append ( $ other ->importNode ( $ target , true ) ); // dup add
843+
844+ // "attributes in xml: namespace are not copied"
845+
846+ $ oxpth = new DOMXPath ( $ other );
847+ $ attribs = $ oxpth ->query ( "//@* " );
848+
849+ foreach ( $ attribs as $ attrib )
850+ if ( $ attrib ->prefix == "xml " )
851+ $ attrib ->parentNode ->removeAttribute ( $ attrib ->nodeName );
852+
853+ $ insert = $ dom ->importNode ( $ frags , true ); // dup
854+ $ xinclude ->parentNode ->insertBefore ( $ insert , $ xinclude ); // add
855+ $ xinclude ->parentNode ->removeChild ( $ xinclude ); // del
856+
857+ $ total ++;
858+ $ changed = true ;
859+ libxml_clear_errors ();
860+ }
861+
862+ if ( ! $ changed )
863+ return $ total ;
821864 }
865+ echo "XInclude nested too deeply (xml:id). \n" ;
866+ errors_are_bad ( -1 );
822867}
823868
824- if ($ total == 0 ) {
825- echo "failed. \n" ;
826- } else {
827- echo "done. Performed $ total XIncludes. \n" ;
869+ function xinclude_run_xpointer ( DOMDocument $ dom ) : int
870+ {
871+ $ total = 0 ;
872+ $ maxrun = 10 ; //LIBXML_VERSION >= 21100 ? 1 : 10;
873+ for ( $ run = 0 ; $ run < $ maxrun ; $ run ++ )
874+ {
875+ echo "$ run " ;
876+ $ status = (int ) $ dom ->xinclude ();
877+
878+ if ( $ status <= 0 )
879+ {
880+ return $ total ;
881+ }
882+ $ total += $ status ;
883+ libxml_clear_errors ();
884+ }
885+ echo "XInclude nested too deeply (xpointer). \n" ;
886+ errors_are_bad ( -1 );
828887}
829- flush ();
830888
831- if ( $ ac [ ' XPOINTER_REPORTING ' ] == ' yes ' || $ ac [ ' LANG ' ] == ' en ' )
889+ function xinclude_report ( )
832890{
891+ global $ ac ;
892+
893+ $ report = $ ac ['XPOINTER_REPORTING ' ] == 'yes ' || $ ac ['LANG ' ] == 'en ' ;
894+ $ output = $ ac ['STDERR_TO_STDOUT ' ] == 'yes ' ? STDOUT : STDERR ;
895+ $ fatal = $ ac ['LANG ' ] == 'en ' ;
896+
833897 $ errors = libxml_get_errors ();
834- $ output = ( $ ac ['STDERR_TO_STDOUT ' ] == 'yes ' ) ? STDOUT : STDERR ;
835- if ( count ( $ errors ) > 0 )
898+ libxml_clear_errors ();
899+
900+ if ( ! $ report )
901+ return ;
902+
903+ $ count = 0 ;
904+ $ prefix = realpath ( __DIR__ );
905+
906+ $ prevLine = -1 ;
907+ $ prevClmn = -1 ;
908+
909+ foreach ( $ errors as $ error )
836910 {
837- fprintf ( $ output , "\n" );
838- foreach ( $ errors as $ error )
839- fprintf ( $ output , "{$ error ->message }\n" );
840- if ( $ ac ['LANG ' ] == 'en ' )
841- errors_are_bad (1 );
911+ $ msg = $ error ->message ;
912+ $ file = $ error ->file ;
913+ $ line = $ error ->line ;
914+ $ clmn = $ error ->column ;
915+
916+ if ( $ prevLine == $ line && $ prevClmn == $ clmn )
917+ continue ; // XPointer failures double reports sometimes
918+ $ prevLine = $ line ;
919+ $ prevClmn = $ clmn ;
920+
921+ $ msg = rtrim ( $ msg );
922+ if ( str_starts_with ( $ file , $ prefix ) )
923+ $ file = substr ( $ file , strlen ( $ prefix ) + 1 );
924+
925+ if ( $ count == 0 )
926+ fprintf ( $ output , "\n" );
927+
928+ fprintf ( $ output , "[ {$ file } {$ line }: {$ clmn }] $ msg \n" );
929+ $ count ++;
930+ }
931+
932+ if ( $ count > 0 )
933+ {
934+ fprintf ( $ output , "\n" );
935+ if ( $ fatal )
936+ errors_are_bad ( 1 );
842937 }
843938}
844939
845- if ( $ ac [ ' LANG ' ] != ' en ' )
940+ function xinclude_residual ( DOMDocument $ dom )
846941{
847942 // XInclude failures are soft errors on translations, so remove
848943 // residual XInclude tags on translations to keep them building.
@@ -868,11 +963,11 @@ function dom_saveload( DOMDocument $dom , string $filename = "" )
868963 case "tbody " :
869964 $ fixup = "<row><entry></entry></row> " ;
870965 break ;
871- // case "variablelist":
872- // $fixup = "<varlistentry><term> ></term><listitem><simpara></simpara></listitem></varlistentry>";
873- // break;
966+ case "variablelist " :
967+ $ fixup = "<varlistentry><term></term><listitem><simpara></simpara></listitem></varlistentry> " ;
968+ break ;
874969 default :
875- echo "Unknown parent element of failed XInclude: $ tagName \n" ;
970+ echo "Unknown parent of failed XInclude: $ tagName \n" ;
876971 $ explain = true ;
877972 continue 2 ;
878973 }
@@ -897,6 +992,23 @@ function dom_saveload( DOMDocument $dom , string $filename = "" )
897992MSG ;
898993 exit (-1 ); // stop here, do not let more messages further confuse the matter
899994 }
995+
996+ // XInclude by xml:id never duplicates xml:id, horever, also using
997+ // XInclude by XPath/XPointer may start causing duplications
998+ // (see docs/structure.md). Crude and ugly fixup ahead, beware!
999+
1000+ $ list = array ();
1001+ $ nodes = $ xpath ->query ( "//*[@xml:id] " );
1002+ foreach ( $ nodes as $ node )
1003+ {
1004+ $ id = $ node ->getAttribute ( "xml:id " );
1005+ if ( isset ( $ list [ $ id ] ) )
1006+ {
1007+ echo " Random removing duplicated xml:id: $ id \n" ;
1008+ $ node ->removeAttribute ( "xml:id " );
1009+ }
1010+ $ list [ $ id ] = $ id ;
1011+ }
9001012}
9011013
9021014echo "Validating {$ ac ["INPUT_FILENAME " ]}... " ;
@@ -997,4 +1109,3 @@ function dom_saveload( DOMDocument $dom , string $filename = "" )
9971109
9981110 errors_are_bad (1 ); // Tell the shell that this script finished with an error.
9991111}
1000- ?>
0 commit comments