@@ -872,8 +872,7 @@ function dom_saveload( DOMDocument $dom , string $filename = "" ) : string
872
872
else
873
873
echo "done. Performed $ total XIncludes. \n" ;
874
874
875
- xinclude_report ();
876
- xinclude_residual ( $ dom );
875
+ xinclude_residual_fixup ( $ dom );
877
876
878
877
function xinclude_run_byid ( DOMDocument $ dom )
879
878
{
@@ -927,94 +926,46 @@ function xinclude_run_byid( DOMDocument $dom )
927
926
928
927
function xinclude_run_xpointer ( DOMDocument $ dom ) : int
929
928
{
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
+
930
932
$ total = 0 ;
931
- $ maxrun = 10 ; //LIBXML_VERSION >= 21100 ? 1 : 10;
932
- for ( $ run = 0 ; $ run < $ maxrun ; $ run ++ )
933
+ for ( $ run = 0 ; $ run < 10 ; $ run ++ )
933
934
{
934
935
echo "$ run " ;
935
- $ status = ( int ) $ dom -> xinclude ();
936
+ libxml_clear_errors ();
936
937
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 )
939
945
return $ total ;
940
- }
941
- $ total += $ status ;
942
- libxml_clear_errors ();
943
946
}
944
947
echo "XInclude nested too deeply (xpointer). \n" ;
945
948
errors_are_bad ( 1 );
946
949
}
947
950
948
- function xinclude_report ( )
951
+ function xinclude_residual_fixup ( DOMDocument $ dom )
949
952
{
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 );
990
954
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
- {
1001
955
// XInclude failures are soft errors on translations, so remove
1002
956
// residual XInclude tags on translations to keep them building.
1003
957
1004
- $ header = false ;
958
+ $ nodes = xinclude_residual_list ( $ dom );
959
+
960
+ $ count = 0 ;
1005
961
$ explain = false ;
1006
962
1007
- $ xpath = new DOMXPath ( $ dom );
1008
- $ xpath ->registerNamespace ( "xi " , "http://www.w3.org/2001/XInclude " );
1009
- $ nodes = $ xpath ->query ( "//xi:include " );
1010
963
foreach ( $ nodes as $ node )
1011
964
{
1012
- if ( $ header == false )
1013
- {
965
+ if ( $ count === 0 )
1014
966
echo "\nFailed XInclude: \n" ;
1015
- $ header = true ;
1016
- }
1017
- echo "- {$ node ->getAttribute ("xpointer " )}\n" ;
967
+ echo " {$ node ->getAttribute ("xpointer " )}\n" ;
968
+ $ count ++;
1018
969
1019
970
$ fixup = null ;
1020
971
$ parent = $ node ->parentNode ;
@@ -1051,9 +1002,6 @@ function xinclude_residual( DOMDocument $dom )
1051
1002
$ node ->parentNode ->removeChild ( $ node );
1052
1003
}
1053
1004
1054
- if ( $ header )
1055
- echo "\n" ;
1056
-
1057
1005
if ( $ explain )
1058
1006
{
1059
1007
echo <<<MSG
@@ -1063,15 +1011,19 @@ function xinclude_residual( DOMDocument $dom )
1063
1011
state. Please report any "Unknown parent" messages on the doc-base
1064
1012
repository, and focus on fixing XInclude/XPointers failures above. \n\n
1065
1013
MSG ;
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
1067
1015
}
1068
1016
1017
+ if ( $ count > 0 )
1018
+ echo "\n" ;
1019
+
1069
1020
// XInclude by xml:id never duplicates xml:id, horever, also using
1070
1021
// XInclude by XPath/XPointer may start causing duplications
1071
1022
// (see docs/structure.md). Crude and ugly fixup ahead, beware!
1072
1023
1024
+ $ list = [];
1073
1025
$ see = false ;
1074
- $ list = array ( );
1026
+ $ xpath = new DOMXPath ( $ dom );
1075
1027
$ nodes = $ xpath ->query ( "//*[@xml:id] " );
1076
1028
foreach ( $ nodes as $ node )
1077
1029
{
@@ -1089,6 +1041,64 @@ function xinclude_residual( DOMDocument $dom )
1089
1041
}
1090
1042
if ( $ see )
1091
1043
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" ;
1092
1102
}
1093
1103
1094
1104
echo "Validating {$ ac ["INPUT_FILENAME " ]}... " ;
0 commit comments