@@ -774,47 +774,108 @@ function getFileModificationHistory(): array {
774
774
}
775
775
echo "done. \n" ;
776
776
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 )
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
+ $ 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 ;
793
835
}
836
+ echo "XInclude nested too deeply (xml:id). \n" ;
837
+ errors_are_bad ( -1 );
794
838
}
795
839
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 );
800
855
}
801
- flush ();
802
856
803
- if ( $ ac [ ' XPOINTER_REPORTING ' ] == ' yes ' || $ ac [ ' LANG ' ] == ' en ' )
857
+ function xinclude_report ( )
804
858
{
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
+
805
865
$ 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 )
808
869
{
809
- fprintf ( $ output , "\n" );
870
+ fprintf ( $ output , "\n\n " );
810
871
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 );
814
875
}
815
876
}
816
877
817
- if ( $ ac [ ' LANG ' ] != ' en ' )
878
+ function xinclude_residual ( DOMDocument $ dom )
818
879
{
819
880
// XInclude failures are soft errors on translations, so remove
820
881
// residual XInclude tags on translations to keep them building.
@@ -869,6 +930,23 @@ function getFileModificationHistory(): array {
869
930
MSG ;
870
931
exit (-1 ); // stop here, do not let more messages further confuse the matter
871
932
}
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
+ }
872
950
}
873
951
874
952
echo "Validating {$ ac ["INPUT_FILENAME " ]}... " ;
0 commit comments