Skip to content

Commit aa9c6a2

Browse files
alfsbAndré L F S Baccijordikroon
authored
XML Entities, individual and grouped (#183)
* XML Entities, partial implantation * Mass conv/split tools. * Example -dist files * Idempotence and opt-in / * Detect duplicated entity names on first language * Rebase Co-authored-by: André L F S Bacci <ae@php.net> Co-authored-by: Jordi Kroon <jkroon@onyourmarks.agency>
1 parent d0d9c8b commit aa9c6a2

7 files changed

Lines changed: 676 additions & 0 deletions

File tree

entities/global.ent-dist

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="utf8" ?>
2+
<!--
3+
This is a "global" XML Entity file.
4+
See doc-base/script/entities.php for details.
5+
6+
Place here only small entities that are expected NOT
7+
being replaced or translated in any part of the manual.
8+
9+
DO NOT COPY OR TRANSLATE THIS FILE.
10+
11+
If you want/need to translate some entity placed here,
12+
open an issue on doc-base or doc-en repository, so the
13+
translatable entity is moved to manual.ent.
14+
-->
15+
<entities xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
16+
17+
<!-- <entity name="ent.name">XML fragment</entity> -->
18+
19+
</entities>

entities/manual.ent-dist

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="utf8" ?>
2+
<!-- $Revision:$ -->
3+
<!--
4+
This is a "manual" XML Entity file.
5+
See doc-base/script/entities.php for details.
6+
7+
Place here only small entities that are expected to be
8+
translated and/or replaced in any part of the manual.
9+
-->
10+
<entities xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
11+
12+
<!-- <entity name="ent.name">XML fragment</entity> -->
13+
14+
</entities>

entities/remove.ent-dist

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="utf8" ?>
2+
<!--
3+
This is a "remove" XML Entity file.
4+
See doc-base/script/entities.php for details.
5+
6+
Place here only deprecated entities that are expected NOT
7+
be being used in any part of the manual.
8+
9+
DO NOT COPY OR TRANSLATE THIS FILE.
10+
11+
If an entity moved here is used in a language in your control,
12+
this means that the entity on the original file is planned to be
13+
removed, or already was removed. Consult the original text file
14+
and apply changes accordly.
15+
-->
16+
<entities xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
17+
18+
<!-- <entity name="ent.name">XML fragment</entity> -->
19+
20+
</entities>

manual.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
<!ENTITY % configure SYSTEM "./temp/manual.conf">
66
%configure;
77

8+
<!-- Entities collected by entities.php -->
9+
<!ENTITY % manual-entities SYSTEM "./temp/entities.ent">
10+
%manual-entities;
11+
812
<!-- Translation layer, if any -->
913
%translation-defs;
1014
%translation-snippets;

scripts/dtdent-conv.php

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php /*
2+
+----------------------------------------------------------------------+
3+
| Copyright (c) 1997-2023 The PHP Group |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| https://www.php.net/license/3_01.txt. |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| license@php.net, so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Authors: André L F S Bacci <ae php.net> |
14+
+----------------------------------------------------------------------+
15+
| Description: Convert DTD Entities files into XML Entities files. |
16+
+----------------------------------------------------------------------+
17+
18+
See `entities.php` for detailed rationale.
19+
20+
Use this for converting bundled entities files that use <!ENTITY> into
21+
XML version used by `entities.php`.
22+
23+
After converting, add the generated entities in an global.ent or
24+
manual.ent file, and delete the previous one.
25+
26+
After all old style .ent files are split or converted, this script can
27+
be removed. */
28+
29+
ini_set( 'display_errors' , 1 );
30+
ini_set( 'display_startup_errors' , 1 );
31+
error_reporting( E_ALL );
32+
33+
if ( count( $argv ) < 2 )
34+
die(" Syntax: php $argv[0] infile\n" );
35+
36+
$infile = $argv[1];
37+
38+
$content = file_get_contents( $infile );
39+
40+
$pos1 = 0;
41+
while ( true )
42+
{
43+
$pos1 = strpos( $content , "<!ENTITY", $pos1 );
44+
if ( $pos1 === false ) break;
45+
46+
$posS = strpos( $content , "'" , $pos1 );
47+
$posD = strpos( $content , '"' , $pos1 );
48+
49+
if ( $posS < $posD )
50+
$q = "'";
51+
else
52+
$q = '"';
53+
54+
$pos1 += 8;
55+
$pos2 = min( $posS , $posD ) + 1;
56+
$pos3 = strpos( $content , $q , $pos2 );
57+
58+
$name = substr( $content , $pos1 , $pos2 - $pos1 - 1 );
59+
$text = substr( $content , $pos2 , $pos3 - $pos2 );
60+
61+
// weird &ugly; ass, namespace correct, DOMDocumentFragment -> DOMNodeList (ampunstand intended)
62+
63+
$name = trim( $name );
64+
$text = str_replace( "&" , "&amp;" , $text );
65+
66+
$frag = "<entities xmlns='http://docbook.org/ns/docbook' xmlns:xlink='http://www.w3.org/1999/xlink'>\n";
67+
$frag .= " <entity name='$name'>$text</entity>\n";
68+
$frag .= '</entities>';
69+
70+
$dom = new DOMDocument( '1.0' , 'utf8' );
71+
$dom->recover = true;
72+
$dom->resolveExternals = false;
73+
libxml_use_internal_errors( true );
74+
75+
$dom->loadXML( $frag , LIBXML_NSCLEAN );
76+
$dom->normalizeDocument();
77+
78+
libxml_clear_errors();
79+
80+
$text = $dom->saveXML( $dom->getElementsByTagName( "entity" )[0] );
81+
$text = str_replace( "&amp;" , "&" , $text );
82+
83+
echo "\n$text\n";
84+
}

scripts/dtdent-split.php

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<?php /*
2+
+----------------------------------------------------------------------+
3+
| Copyright (c) 1997-2023 The PHP Group |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| https://www.php.net/license/3_01.txt. |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| license@php.net, so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Authors: André L F S Bacci <ae php.net> |
14+
+----------------------------------------------------------------------+
15+
| Description: Split old DTD .ent file into individual XML files. |
16+
+----------------------------------------------------------------------+
17+
18+
See `entities.php` for detailed rationale.
19+
20+
Use this for spliting `language-snippets-ent` and possible other DTD
21+
entities files into individual .xml files.
22+
23+
After spliting, add generated files under doc-lang/entities/ , and
24+
the original file, in one go.
25+
26+
After all DTD .ent files are split or converted, this script can
27+
be removed. */
28+
29+
ini_set( 'display_errors' , 1 );
30+
ini_set( 'display_startup_errors' , 1 );
31+
error_reporting( E_ALL );
32+
33+
if ( count( $argv ) < 3 )
34+
die(" Syntax: php $argv[0] infile outdir [hash user]\n" );
35+
36+
$infile = $argv[1];
37+
$outdir = $argv[2];
38+
$hash = $argv[3] ?? "";
39+
$user = $argv[4] ?? "_";
40+
41+
$content = file_get_contents( $infile );
42+
$entities = [];
43+
44+
// Parse
45+
46+
$pos1 = 0;
47+
while ( true )
48+
{
49+
$pos1 = strpos( $content , "<!ENTITY", $pos1 );
50+
if ( $pos1 === false ) break;
51+
52+
$posS = strpos( $content , "'" , $pos1 );
53+
$posD = strpos( $content , '"' , $pos1 );
54+
55+
if ( $posS < $posD )
56+
$q = "'";
57+
else
58+
$q = '"';
59+
60+
$pos1 += 8;
61+
$pos2 = min( $posS , $posD ) + 1;
62+
$pos3 = strpos( $content , $q , $pos2 );
63+
64+
$name = substr( $content , $pos1 , $pos2 - $pos1 - 1 );
65+
$text = substr( $content , $pos2 , $pos3 - $pos2 );
66+
67+
$name = trim( $name );
68+
69+
$entities[$name] = $text;
70+
}
71+
72+
// Check
73+
74+
foreach( $entities as $name => $text )
75+
{
76+
$file = "$outdir/$name.xml";
77+
if ( file_exists( $file ) )
78+
echo( "Entity name colision, OVERWROTE: $file\n" );
79+
}
80+
81+
// Write
82+
83+
foreach( $entities as $name => $text )
84+
{
85+
$file = "$outdir/$name.xml";
86+
87+
if ( $hash == "" )
88+
$header = '<!-- $Revision$ -->';
89+
else
90+
$header .= "<!-- EN-Revision: $hash Maintainer: $user Status: ready --><!-- CREDITS: $user -->\n";
91+
92+
file_put_contents( $file , $header . $text );
93+
}
94+
95+
// Test
96+
97+
$dom = new DOMDocument();
98+
$dom->recover = true;
99+
$dom->resolveExternals = false;
100+
libxml_use_internal_errors( true );
101+
102+
foreach( $entities as $name => $text )
103+
{
104+
$file = "$outdir/$name.xml";
105+
106+
$text = file_get_contents( $file );
107+
$text = "<frag>$text</frag>";
108+
109+
$dom->loadXML( $text );
110+
$err = libxml_get_errors();
111+
libxml_clear_errors();
112+
113+
foreach( $err as $e )
114+
{
115+
$msg = trim( $e->message );
116+
if ( str_starts_with( $msg , "Entity '" ) && str_ends_with( $msg , "' not defined" ) )
117+
continue;
118+
die( "Failed to load $file\n" );
119+
}
120+
}
121+
122+
$total = count( $entities );
123+
print "Generated $total files.\n";

0 commit comments

Comments
 (0)