@@ -872,8 +872,7 @@ function dom_saveload( DOMDocument $dom , string $filename = "" ) : string
872872else
873873 echo "done. Performed $ total XIncludes. \n" ;
874874
875- xinclude_report ();
876- xinclude_residual ( $ dom );
875+ xinclude_residual_fixup ( $ dom );
877876
878877function xinclude_run_byid ( DOMDocument $ dom )
879878{
@@ -927,94 +926,46 @@ function xinclude_run_byid( DOMDocument $dom )
927926
928927function xinclude_run_xpointer ( DOMDocument $ dom ) : int
929928{
929+ // The return of xinclude() cannot be used for counting or stoping, as it
930+ // sometimes return zero/negative in cases of partial executions
931+
930932 $ total = 0 ;
931- $ maxrun = 10 ; //LIBXML_VERSION >= 21100 ? 1 : 10;
932- for ( $ run = 0 ; $ run < $ maxrun ; $ run ++ )
933+ for ( $ run = 0 ; $ run < 10 ; $ run ++ )
933934 {
934935 echo "$ run " ;
935- $ status = ( int ) $ dom -> xinclude ();
936+ libxml_clear_errors ();
936937
937- if ( $ status <= 0 )
938- {
938+ $ was = count ( xinclude_residual_list ( $ dom ) );
939+ $ dom ->xinclude ();
940+ $ now = count ( xinclude_residual_list ( $ dom ) );
941+
942+ $ total += $ was - $ now ;
943+
944+ if ( $ was === $ now )
939945 return $ total ;
940- }
941- $ total += $ status ;
942- libxml_clear_errors ();
943946 }
944947 echo "XInclude nested too deeply (xpointer). \n" ;
945948 errors_are_bad ( 1 );
946949}
947950
948- function xinclude_report ( )
951+ function xinclude_residual_fixup ( DOMDocument $ dom )
949952{
950- global $ ac ;
951-
952- $ report = $ ac ['XPOINTER_REPORTING ' ] == 'yes ' || $ ac ['LANG ' ] == 'en ' ;
953- $ output = $ ac ['STDERR_TO_STDOUT ' ] == 'yes ' ? STDOUT : STDERR ;
954- $ fatal = $ ac ['LANG ' ] == 'en ' ;
955-
956- $ errors = libxml_get_errors ();
957- libxml_clear_errors ();
958-
959- if ( ! $ report )
960- return ;
961-
962- $ count = 0 ;
963- $ prefix = realpath ( __DIR__ );
964-
965- $ prevLine = -1 ;
966- $ prevClmn = -1 ;
967-
968- foreach ( $ errors as $ error )
969- {
970- $ msg = $ error ->message ;
971- $ file = $ error ->file ;
972- $ line = $ error ->line ;
973- $ clmn = $ error ->column ;
974-
975- if ( $ prevLine == $ line && $ prevClmn == $ clmn )
976- continue ; // XPointer failures double reports sometimes
977- $ prevLine = $ line ;
978- $ prevClmn = $ clmn ;
979-
980- $ msg = rtrim ( $ msg );
981- if ( str_starts_with ( $ file , $ prefix ) )
982- $ file = substr ( $ file , strlen ( $ prefix ) + 1 );
983-
984- if ( $ count == 0 )
985- fprintf ( $ output , "\n" );
986-
987- fprintf ( $ output , "[ {$ file } {$ line }: {$ clmn }] $ msg \n" );
988- $ count ++;
989- }
953+ xinclude_debug_report ( $ dom );
990954
991- if ( $ count > 0 )
992- {
993- fprintf ( $ output , "\n" );
994- if ( $ fatal )
995- errors_are_bad ( 1 );
996- }
997- }
998-
999- function xinclude_residual ( DOMDocument $ dom )
1000- {
1001955 // XInclude failures are soft errors on translations, so remove
1002956 // residual XInclude tags on translations to keep them building.
1003957
1004- $ header = false ;
958+ $ nodes = xinclude_residual_list ( $ dom );
959+
960+ $ count = 0 ;
1005961 $ explain = false ;
1006962
1007- $ xpath = new DOMXPath ( $ dom );
1008- $ xpath ->registerNamespace ( "xi " , "http://www.w3.org/2001/XInclude " );
1009- $ nodes = $ xpath ->query ( "//xi:include " );
1010963 foreach ( $ nodes as $ node )
1011964 {
1012- if ( $ header == false )
1013- {
965+ if ( $ count === 0 )
1014966 echo "\nFailed XInclude: \n" ;
1015- $ header = true ;
1016- }
1017- echo "- {$ node ->getAttribute ("xpointer " )}\n" ;
967+ echo " {$ node ->getAttribute ("xpointer " )}\n" ;
968+ $ count ++;
1018969
1019970 $ fixup = null ;
1020971 $ parent = $ node ->parentNode ;
@@ -1051,9 +1002,6 @@ function xinclude_residual( DOMDocument $dom )
10511002 $ node ->parentNode ->removeChild ( $ node );
10521003 }
10531004
1054- if ( $ header )
1055- echo "\n" ;
1056-
10571005 if ( $ explain )
10581006 {
10591007 echo <<<MSG
@@ -1063,15 +1011,19 @@ function xinclude_residual( DOMDocument $dom )
10631011state. Please report any "Unknown parent" messages on the doc-base
10641012repository, and focus on fixing XInclude/XPointers failures above. \n\n
10651013MSG ;
1066- exit (1 ); // stop here, do not let more messages further confuse the matter
1014+ exit ( 1 ); // stop here, do not let more messages further confuse the matter
10671015 }
10681016
1017+ if ( $ count > 0 )
1018+ echo "\n" ;
1019+
10691020 // XInclude by xml:id never duplicates xml:id, horever, also using
10701021 // XInclude by XPath/XPointer may start causing duplications
10711022 // (see docs/structure.md). Crude and ugly fixup ahead, beware!
10721023
1024+ $ list = [];
10731025 $ see = false ;
1074- $ list = array ( );
1026+ $ xpath = new DOMXPath ( $ dom );
10751027 $ nodes = $ xpath ->query ( "//*[@xml:id] " );
10761028 foreach ( $ nodes as $ node )
10771029 {
@@ -1089,6 +1041,64 @@ function xinclude_residual( DOMDocument $dom )
10891041 }
10901042 if ( $ see )
10911043 echo " See: https://github.com/php/doc-base/blob/master/docs/structure.md#xmlid-structure \n" ;
1044+
1045+ $ fatal = $ GLOBALS ['ac ' ]['LANG ' ] == 'en ' ;
1046+
1047+ if ( $ see && $ fatal )
1048+ errors_are_bad ( 1 ); // Duplicated strucutral xml:ids are fatal on doc-en
1049+ }
1050+
1051+ function xinclude_residual_list ( DOMDocument $ dom ) : DOMNodeList
1052+ {
1053+ $ xpath = new DOMXPath ( $ dom );
1054+ $ xpath ->registerNamespace ( "xi " , "http://www.w3.org/2001/XInclude " );
1055+ $ nodes = $ xpath ->query ( "//xi:include " );
1056+
1057+ return $ nodes ;
1058+ }
1059+
1060+ function xinclude_debug_report ( DOMDocument $ dom )
1061+ {
1062+ $ debugFile = __DIR__ . "/temp/xinclude-debug.xml " ;
1063+
1064+ dom_saveload ( $ dom , $ debugFile ); // preserve state
1065+
1066+ libxml_clear_errors ();
1067+ $ dom ->xinclude ();
1068+ $ errors = libxml_get_errors ();
1069+ libxml_clear_errors ();
1070+
1071+ dom_saveload ( $ dom ); // normal output
1072+
1073+ $ count = 0 ;
1074+ $ prefix = realpath ( __DIR__ );
1075+
1076+ $ prevLine = -1 ;
1077+ $ prevClmn = -1 ;
1078+
1079+ foreach ( $ errors as $ error )
1080+ {
1081+ $ msg = $ error ->message ;
1082+ $ file = $ error ->file ;
1083+ $ line = $ error ->line ;
1084+ $ clmn = $ error ->column ;
1085+
1086+ $ prevLine = $ line ;
1087+ $ prevClmn = $ clmn ;
1088+
1089+ $ msg = rtrim ( $ msg );
1090+ if ( str_starts_with ( $ file , $ prefix ) )
1091+ $ file = substr ( $ file , strlen ( $ prefix ) + 1 );
1092+
1093+ if ( $ count === 0 )
1094+ echo "\n" ;
1095+
1096+ echo "[ {$ file } {$ line }: {$ clmn }] $ msg \n" ;
1097+ $ count ++;
1098+ }
1099+
1100+ if ( $ count === 0 )
1101+ echo "\n" ;
10921102}
10931103
10941104echo "Validating {$ ac ["INPUT_FILENAME " ]}... " ;
0 commit comments