@@ -775,46 +775,108 @@ function getFileModificationHistory(): array {
775
775
echo "done. \n" ;
776
776
777
777
echo "Running XInclude/XPointer... " ;
778
- $ total = 0 ;
779
- $ maxrun = 10 ; //LIBXML_VERSION >= 21100 ? 1 : 10;
780
- for ( $ run = 0 ; $ run < $ maxrun ; $ run ++ )
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 )
781
791
{
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 ++ )
790
795
{
791
- echo "Recursive XInclude is too deep. \n" ;
792
- errors_are_bad (-1 );
796
+ echo "$ run " ;
797
+ $ xpath = new DOMXPath ( $ dom );
798
+ $ xpath ->registerNamespace ( "xi " , "http://www.w3.org/2001/XInclude " );
799
+ $ xincludes = $ xpath ->query ( "//xi:include " );
800
+
801
+ $ progress = false ;
802
+ foreach ( $ xincludes as $ xinclude )
803
+ {
804
+ $ xpointer = $ xinclude ->getAttribute ( "xpointer " );
805
+ $ target = $ xinclude ->ownerDocument ->getElementById ( $ xpointer );
806
+
807
+ if ( $ target == null )
808
+ continue ;
809
+
810
+ $ other = new DOMDocument ( '1.0 ' , 'utf8 ' );
811
+ $ frags = $ other ->createDocumentFragment ();
812
+ $ other ->append ( $ frags );
813
+ $ frags ->append ( $ other ->importNode ( $ target , true ) ); // dup add
814
+
815
+ // "attributes in xml: namespace are not copied"
816
+
817
+ $ oxpth = new DOMXPath ( $ other );
818
+ $ attribs = $ oxpth ->query ( "//@* " );
819
+
820
+ foreach ( $ attribs as $ attrib )
821
+ if ( $ attrib ->prefix == "xml " )
822
+ $ attrib ->parentNode ->removeAttribute ( $ attrib ->nodeName );
823
+
824
+ $ insert = $ dom ->importNode ( $ frags , true ); // dup
825
+ $ xinclude ->parentNode ->insertBefore ( $ insert , $ xinclude ); // add
826
+ $ xinclude ->parentNode ->removeChild ( $ xinclude ); // del
827
+
828
+ $ progress = true ;
829
+ $ total ++;
830
+ }
831
+
832
+ if ( $ progress )
833
+ continue ;
834
+ else
835
+ return $ total ;
793
836
}
837
+ echo "XInclude nested too deeply (xml:id). \n" ;
838
+ errors_are_bad ( -1 );
794
839
}
795
840
796
- if ($ total == 0 ) {
797
- echo "failed. \n" ;
798
- } else {
799
- echo "done. Performed $ total XIncludes. \n" ;
841
+ function xinclude_run_xpointer ( DOMDocument $ dom ) : int
842
+ {
843
+ $ total = 0 ;
844
+ $ maxrun = 10 ; //LIBXML_VERSION >= 21100 ? 1 : 10;
845
+ for ( $ run = 0 ; $ run < $ maxrun ; $ run ++ )
846
+ {
847
+ echo "$ run " ;
848
+ libxml_clear_errors ();
849
+ $ status = (int ) $ dom ->xinclude ();
850
+ if ( $ status <= 0 )
851
+ return $ total ;
852
+ $ total += $ status ;
853
+ }
854
+ echo "XInclude nested too deeply (xpointer). \n" ;
855
+ errors_are_bad ( -1 );
800
856
}
801
- flush ();
802
857
803
- if ( $ ac [ ' XPOINTER_REPORTING ' ] == ' yes ' || $ ac [ ' LANG ' ] == ' en ' )
858
+ function xinclude_report ( )
804
859
{
860
+ global $ ac ;
861
+
862
+ $ report = $ ac ['XPOINTER_REPORTING ' ] == 'yes ' || $ ac ['LANG ' ] == 'en ' ;
863
+ $ output = $ ac ['STDERR_TO_STDOUT ' ] == 'yes ' ? STDOUT : STDERR ;
864
+ $ fatal = $ ac ['LANG ' ] == 'en ' ;
865
+
805
866
$ errors = libxml_get_errors ();
806
- $ output = ( $ ac ['STDERR_TO_STDOUT ' ] == 'yes ' ) ? STDOUT : STDERR ;
807
- if ( count ( $ errors ) > 0 )
867
+ libxml_clear_errors ();
868
+
869
+ if ( count ( $ errors ) > 0 && $ report )
808
870
{
809
- fprintf ( $ output , "\n" );
871
+ fprintf ( $ output , "\n\n " );
810
872
foreach ( $ errors as $ error )
811
- fprintf ( $ output , "{ $ error ->message }\n" );
812
- if ( $ ac [ ' LANG ' ] == ' en ' )
813
- errors_are_bad (1 );
873
+ fprintf ( $ output , rtrim ( $ error ->message ) . "\n\n" );
874
+ if ( $ fatal )
875
+ errors_are_bad ( 1 );
814
876
}
815
877
}
816
878
817
- if ( $ ac [ ' LANG ' ] != ' en ' )
879
+ function xinclude_residual ( DOMDocument $ dom )
818
880
{
819
881
// XInclude failures are soft errors on translations, so remove
820
882
// residual XInclude tags on translations to keep them building.
@@ -844,7 +906,7 @@ function getFileModificationHistory(): array {
844
906
// $fixup = "<varlistentry><term>></term><listitem><simpara></simpara></listitem></varlistentry>";
845
907
// break;
846
908
default :
847
- echo "Unknown parent element of failed XInclude: $ tagName \n" ;
909
+ echo "Unknown parent of failed XInclude: $ tagName \n" ;
848
910
$ explain = true ;
849
911
continue 2 ;
850
912
}
@@ -869,6 +931,23 @@ function getFileModificationHistory(): array {
869
931
MSG ;
870
932
exit (-1 ); // stop here, do not let more messages further confuse the matter
871
933
}
934
+
935
+ // XInclude by xml:id never duplicates xml:id, horever, also using
936
+ // XInclude by XPath/XPointer may start causing duplications
937
+ // (see docs/structure.md). Crude and ugly fixup ahead, beware!
938
+
939
+ $ list = array ();
940
+ $ nodes = $ xpath ->query ( "//*[@xml:id] " );
941
+ foreach ( $ nodes as $ node )
942
+ {
943
+ $ id = $ node ->getAttribute ( "xml:id " );
944
+ if ( isset ( $ list [ $ id ] ) )
945
+ {
946
+ echo " Random removing duplicated xml:id: $ id \n" ;
947
+ $ node ->removeAttribute ( "xml:id " );
948
+ }
949
+ $ list [ $ id ] = $ id ;
950
+ }
872
951
}
873
952
874
953
echo "Validating {$ ac ["INPUT_FILENAME " ]}... " ;
@@ -973,4 +1052,3 @@ function getFileModificationHistory(): array {
973
1052
974
1053
errors_are_bad (1 ); // Tell the shell that this script finished with an error.
975
1054
}
976
- ?>
0 commit comments