diff --git a/.gitignore b/.gitignore
index dd22d459a..c0645b229 100644
--- a/.gitignore
+++ b/.gitignore
@@ -642,6 +642,8 @@ autom4te.cache/
/gettext-tools/javaexec.sh
/gettext-tools/libtool
/gettext-tools/stamp-h1
+/gettext-tools/build-aux/xml-validate-10
+/gettext-tools/build-aux/xml-validate-11
/gettext-tools/doc/Makefile
/gettext-tools/emacs/Makefile
/gettext-tools/examples/Makefile
diff --git a/HACKING b/HACKING
index b29b4ab88..60225417c 100644
--- a/HACKING
+++ b/HACKING
@@ -147,6 +147,10 @@ are skipped. To this effect, you need to install also:
- On Debian and Debian-based systems: libxml2-utils,
- On Red Hat distributions: libxml2.
- Other: https://repology.org/project/libxml2/versions
+ * The Xerces2 Java XML parser (binary distribution named 'xml-schema-1.1')
+ + Homepage: https://xerces.apache.org/xerces2-j/
+ + Pre-built package name: --
+ + See gettext-tools/build-aux/xml-validate-11.in for more details.
* A C++ compiler
+ Homepage: https://gcc.gnu.org/
diff --git a/gettext-tools/Makefile.am b/gettext-tools/Makefile.am
index 1d6c665a7..274b9d41a 100644
--- a/gettext-tools/Makefile.am
+++ b/gettext-tools/Makefile.am
@@ -23,6 +23,7 @@ SUBDIRS = gnulib-lib libgrep src libgettextpo po its projects styles emacs misc
EXTRA_DIST = misc/DISCLAIM
MOSTLYCLEANFILES = core *.stackdump
+DISTCLEANFILES = build-aux/xml-validate-10 build-aux/xml-validate-11
# Files installed for use by gettextize.
diff --git a/gettext-tools/build-aux/xml-validate-10.in b/gettext-tools/build-aux/xml-validate-10.in
new file mode 100644
index 000000000..609279ffb
--- /dev/null
+++ b/gettext-tools/build-aux/xml-validate-10.in
@@ -0,0 +1,104 @@
+#!/bin/sh
+# Validating an XML document against an XML Schema 1.0.
+
+# Copyright (C) 2024 Free Software Foundation, Inc.
+#
+# This file is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published
+# by the Free Software Foundation, either version 3 of the License,
+# or (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+# Written by Bruno Haible , 2024.
+
+# func_usage
+# outputs to stdout the --help usage message.
+func_usage ()
+{
+ echo "\
+Usage: xml-validate-10 [OPTION]... SCHEMA DOCUMENT
+
+Invokes an XML Schema 1.0 validator, validating the given XML document
+against the given XML schema.
+
+The exit code is 0 for valid, 1 for invalid.
+
+Options:
+ --help print this help and exit
+ --version print version information and exit
+
+Send patches and bug reports to ."
+}
+
+# func_version
+# outputs to stdout the --version message.
+func_version ()
+{
+ echo "xml-validate-10 (GNU gettext)"
+ echo "Copyright (C) 2024 Free Software Foundation, Inc.
+License GPLv3+: GNU GPL version 3 or later
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law."
+ echo
+ printf 'Written by %s.\n' "Bruno Haible"
+}
+
+# func_fatal_error message
+# outputs to stderr a fatal error message, and terminates the program.
+func_fatal_error ()
+{
+ echo "xml-validate-10: *** $1" 1>&2
+ echo "xml-validate-10: *** Stop." 1>&2
+ exit 1
+}
+
+# Outputs a command and runs it.
+func_verbose ()
+{
+ # Make it easy to copy&paste the printed command into a shell in most cases,
+ # by escaping '\\', '"', and '$'. This is not perfect, just good enough.
+ echo "$@" | sed -e 's/\([\\"$]\)/\\\1/g'
+ "$@"
+}
+
+# Command-line option processing.
+while test $# -gt 0; do
+ case "$1" in
+ --help | --hel | --he | --h )
+ func_usage
+ exit 0 ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v )
+ func_version
+ exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ -* )
+ func_fatal_error "unrecognized option: $1"
+ ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# -lt 2; then
+ func_fatal_error "too few arguments"
+fi
+if test $# -gt 2; then
+ func_fatal_error "too many arguments"
+fi
+
+schema="$1"
+document="$2"
+shift
+shift
+
+if test '@XMLLINT@' != ':'; then
+ func_verbose @XMLLINT@ --noout --schema "$schema" "$document" || exit 1
+fi
diff --git a/gettext-tools/build-aux/xml-validate-11.in b/gettext-tools/build-aux/xml-validate-11.in
new file mode 100644
index 000000000..c7d08e623
--- /dev/null
+++ b/gettext-tools/build-aux/xml-validate-11.in
@@ -0,0 +1,189 @@
+#!/bin/sh
+# Validating an XML document against an XML Schema 1.1.
+
+# Copyright (C) 2024 Free Software Foundation, Inc.
+#
+# This file is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published
+# by the Free Software Foundation, either version 3 of the License,
+# or (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+# Written by Bruno Haible , 2024.
+
+# The major advantages of XML Schema 1.1, compared to XML Schema 1.0, are:
+# * It fixes an ill-designed "Unique Particle Attribution" rule
+#
+#
+# that makes
+#
+# elements practically useless. See
+#
+# .
+# * It allows to check that, for example, a specific child element and a
+# specific attribute are not used together in the same XML element.
+# This is a special case of .
+#
+# The major drawback of XML Schema 1.1, compared to XML Schema 1.0, are:
+# * (As of 2024) There is only one Free Software implementation of it:
+# Apache Xerces in version 2.12 or newer, in the "xml-schema-1.1" variant.
+# * The error messages emitted by Apache Xerces are regularly mysterious /
+# unintelligible.
+
+# func_usage
+# outputs to stdout the --help usage message.
+func_usage ()
+{
+ echo "\
+Usage: xml-validate-11 [OPTION]... SCHEMA DOCUMENT
+
+Invokes an XML Schema 1.1 validator, validating the given XML document
+against the given XML schema.
+
+The exit code is 0 for valid, 1 for invalid.
+
+Options:
+ --help print this help and exit
+ --version print version information and exit
+
+The environment variable XERCES_J_DIR should point to a directory that
+contains a binary distribution of Xerces-J version 2.12 (or newer),
+in xml-schema-1.1 variant. Download location:
+https://dlcdn.apache.org//xerces/j/binaries/Xerces-J-bin.2.12.2-xml-schema-1.1.tar.gz
+
+Send patches and bug reports to ."
+}
+
+# func_version
+# outputs to stdout the --version message.
+func_version ()
+{
+ echo "xml-validate-11 (GNU gettext)"
+ echo "Copyright (C) 2024 Free Software Foundation, Inc.
+License GPLv3+: GNU GPL version 3 or later
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law."
+ echo
+ printf 'Written by %s.\n' "Bruno Haible"
+}
+
+# func_fatal_error message
+# outputs to stderr a fatal error message, and terminates the program.
+func_fatal_error ()
+{
+ echo "xml-validate-11: *** $1" 1>&2
+ echo "xml-validate-11: *** Stop." 1>&2
+ exit 1
+}
+
+# Outputs a command and runs it.
+func_verbose ()
+{
+ # Make it easy to copy&paste the printed command into a shell in most cases,
+ # by escaping '\\', '"', and '$'. This is not perfect, just good enough.
+ echo "$@" | sed -e 's/\([\\"$]\)/\\\1/g'
+ "$@"
+}
+
+# func_tmpdir
+# creates a temporary directory.
+# Sets variable
+# - tmp pathname of freshly created temporary directory
+func_tmpdir ()
+{
+ # Use the environment variable TMPDIR, falling back to /tmp. This allows
+ # users to specify a different temporary directory, for example, if their
+ # /tmp is filled up or too small.
+ : "${TMPDIR=/tmp}"
+ {
+ # Use the mktemp program if available. If not available, hide the error
+ # message.
+ tmp=`(umask 077 && mktemp -d -q "$TMPDIR/gtXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+ } ||
+ {
+ # Use a simple mkdir command. It is guaranteed to fail if the directory
+ # already exists. $RANDOM is bash specific and expands to empty in shells
+ # other than bash, ksh and zsh. Its use does not increase security;
+ # rather, it minimizes the probability of failure in a very cluttered /tmp
+ # directory.
+ tmp=$TMPDIR/gt$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+ } ||
+ {
+ echo "$0: cannot create a temporary directory in $TMPDIR" >&2
+ { (exit 1); exit 1; }
+ }
+}
+
+# Command-line option processing.
+while test $# -gt 0; do
+ case "$1" in
+ --help | --hel | --he | --h )
+ func_usage
+ exit 0 ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v )
+ func_version
+ exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ -* )
+ func_fatal_error "unrecognized option: $1"
+ ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# -lt 2; then
+ func_fatal_error "too few arguments"
+fi
+if test $# -gt 2; then
+ func_fatal_error "too many arguments"
+fi
+
+schema="$1"
+document="$2"
+shift
+shift
+
+if test -n '@HAVE_JAVAEXEC@' \
+ && test -n "$XERCES_J_DIR" \
+ && test -d "$XERCES_J_DIR" \
+ && test -f "$XERCES_J_DIR/xercesSamples.jar" \
+ && test -f "$XERCES_J_DIR/xercesImpl.jar" \
+ && test -f "$XERCES_J_DIR/org.eclipse.wst.xml.xpath2.processor_1.2.1.jar" \
+ && test -f "$XERCES_J_DIR/cupv10k-runtime.jar"; then
+ # We don't need to write our own Java program that invokes the validator,
+ # like
+ # or ,
+ # because the Xerces-J FAQ
+ # says:
+ # "You can also refer to the JAXP sample, SourceValidator, where you can
+ # validate XML documents against 1.1 schemas by specifying an option
+ # "-xsd11" when running the sample."
+ # Documentation of this sample:
+ #
+ func_tmpdir
+ echo "sh ../javaexec.sh jaxp.SourceValidator -xsd11 -f -a $schema -i $document"
+ CLASSPATH="$XERCES_J_DIR/xercesSamples.jar:$XERCES_J_DIR/xercesImpl.jar:$XERCES_J_DIR/org.eclipse.wst.xml.xpath2.processor_1.2.1.jar:$XERCES_J_DIR/cupv10k-runtime.jar" \
+ sh ../javaexec.sh jaxp.SourceValidator -xsd11 -f -a "$schema" -i "$document" \
+ > "$tmp"/out 2> "$tmp"/err
+ # The exit code is usually 0, even if there were errors.
+ if test $? != 0 || grep '\[Error\]' "$tmp"/err >/dev/null; then
+ exitcode=1
+ else
+ exitcode=0
+ fi
+ cat "$tmp"/err 1>&2
+ cat "$tmp"/out
+ rm -f "$tmp"/out "$tmp"/err
+ exit $exitcode
+fi
diff --git a/gettext-tools/configure.ac b/gettext-tools/configure.ac
index b9c131170..86e4f1725 100644
--- a/gettext-tools/configure.ac
+++ b/gettext-tools/configure.ac
@@ -618,6 +618,7 @@ AM_CONDITIONAL([TEST_SYSTEM_LIBINTL], [test $USE_INCLUDED_LIBINTL = no])
dnl Checks for optional programs for the its/* tests.
AC_PATH_PROGS([XMLLINT], [xmllint], [:])
+AC_SUBST([HAVE_JAVAEXEC])
AC_CONFIG_SUBDIRS([examples])
@@ -664,4 +665,9 @@ AC_CONFIG_FILES([system-tests/Makefile])
AC_CONFIG_FILES([gnulib-tests/Makefile])
+AC_CONFIG_FILES([build-aux/xml-validate-10],
+ [chmod a+x build-aux/xml-validate-10])
+AC_CONFIG_FILES([build-aux/xml-validate-11],
+ [chmod a+x build-aux/xml-validate-11])
+
AC_OUTPUT
diff --git a/gettext-tools/doc/gettext.texi b/gettext-tools/doc/gettext.texi
index a2cbb3c11..6a644b127 100644
--- a/gettext-tools/doc/gettext.texi
+++ b/gettext-tools/doc/gettext.texi
@@ -10879,8 +10879,9 @@ second ("A non-translatable string"), the following ITS rules can be used:
@end example
ITS rules files must have the @file{.its} file extension and obey
-the XML schema encoded by
-@code{its.xsd} and its auxiliary schema @code{its-extensions.xsd}.
+the XML schema version 1.0 encoded by @code{its.xsd10} or
+the XML schema version 1.1 encoded by @code{its.xsd11}
+and its auxiliary schema @code{its-extensions.xsd}.
@node Locating Rules
@subsubsection Specifying where to find the ITS Rules
@@ -10924,7 +10925,8 @@ of @code{locatingRule} or @code{documentRule}. If it is specified in a
have the @code{target} attribute.
Locating rules files must have the @file{.loc} file extension and obey
-the XML schema encoded by @code{locating-rules.xsd}.
+the XML schema version 1.0 encoded by @code{locating-rules.xsd10} or
+the XML schema version 1.1 encoded by @code{locating-rules.xsd11}.
Both ITS rules files and locating rules files must be installed in the
@file{$prefix/share/gettext/its} directory. Once those files are
properly installed, @code{xgettext} can extract translatable strings
diff --git a/gettext-tools/its/Makefile.am b/gettext-tools/its/Makefile.am
index e372a4311..9066e7bfd 100644
--- a/gettext-tools/its/Makefile.am
+++ b/gettext-tools/its/Makefile.am
@@ -38,15 +38,17 @@ dist_its_DATA = $(ITS_FILES) $(LOC_FILES)
# Checks the XML files against their schemas.
# Work around .
check-local:
- @if echo '' | $(XMLLINT) --noout --schema $(top_srcdir)/src/its.xsd - >/dev/null 2>&1; then \
- for file in $(ITS_FILES); do \
- echo "Checking $$file..."; \
- echo "$(XMLLINT) --noout --schema $(top_srcdir)/src/its.xsd $(srcdir)/$$file"; \
- $(XMLLINT) --noout --schema $(top_srcdir)/src/its.xsd $(srcdir)/$$file || exit 1; \
- done; \
- fi
+ @for file in $(ITS_FILES); do \
+ echo "Checking $$file..."; \
+ echo "$(top_builddir)/build-aux/xml-validate-10 $(top_srcdir)/src/its.xsd10 $(srcdir)/$$file"; \
+ $(top_builddir)/build-aux/xml-validate-10 $(top_srcdir)/src/its.xsd10 $(srcdir)/$$file || exit 1; \
+ echo "$(top_builddir)/build-aux/xml-validate-11 $(top_srcdir)/src/its.xsd11 $(srcdir)/$$file"; \
+ $(top_builddir)/build-aux/xml-validate-11 $(top_srcdir)/src/its.xsd11 $(srcdir)/$$file || exit 1; \
+ done
@for file in $(LOC_FILES); do \
echo "Checking $$file..."; \
- echo "$(XMLLINT) --noout --schema $(top_srcdir)/src/locating-rules.xsd $(srcdir)/$$file"; \
- $(XMLLINT) --noout --schema $(top_srcdir)/src/locating-rules.xsd $(srcdir)/$$file || exit 1; \
+ echo "$(top_builddir)/build-aux/xml-validate-10 $(top_srcdir)/src/locating-rules.xsd10 $(srcdir)/$$file"; \
+ $(top_builddir)/build-aux/xml-validate-10 $(top_srcdir)/src/locating-rules.xsd10 $(srcdir)/$$file || exit 1; \
+ echo "$(top_builddir)/build-aux/xml-validate-11 $(top_srcdir)/src/locating-rules.xsd11 $(srcdir)/$$file"; \
+ $(top_builddir)/build-aux/xml-validate-11 $(top_srcdir)/src/locating-rules.xsd11 $(srcdir)/$$file || exit 1; \
done
diff --git a/gettext-tools/src/Makefile.am b/gettext-tools/src/Makefile.am
index cd94c3895..9dd79b266 100644
--- a/gettext-tools/src/Makefile.am
+++ b/gettext-tools/src/Makefile.am
@@ -796,8 +796,8 @@ uninstall-tcl:
# Special rules for XML schemas.
schema_DATA = \
- its.xsd its-extensions.xsd \
- locating-rules.xsd
+ its.xsd10 its.xsd11 its-extensions.xsd \
+ locating-rules.xsd10 locating-rules.xsd11
EXTRA_DIST += $(schema_DATA)
diff --git a/gettext-tools/src/its.xsd10 b/gettext-tools/src/its.xsd10
new file mode 100644
index 000000000..326edfbe1
--- /dev/null
+++ b/gettext-tools/src/its.xsd10
@@ -0,0 +1,139 @@
+
+
+
+
+ XML schema 1.0 of *.its files, as understood by GNU gettext.
+
+Copyright (C) 2015-2024 Free Software Foundation, Inc.
+
+This file is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation, either version 3 of the License,
+or (at your option) any later version.
+
+This file is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+Written by Bruno Haible <bruno@clisp.org>, 2024.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Note: An instance should not have both the 'locNotePointer' attribute and a 'locNote' child at the same time.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gettext-tools/src/its.xsd b/gettext-tools/src/its.xsd11
similarity index 96%
rename from gettext-tools/src/its.xsd
rename to gettext-tools/src/its.xsd11
index 21cd7f454..5280bbaf3 100644
--- a/gettext-tools/src/its.xsd
+++ b/gettext-tools/src/its.xsd11
@@ -2,7 +2,7 @@
- XML schema of *.its files, as understood by GNU gettext.
+ XML schema 1.1 of *.its files, as understood by GNU gettext.
Copyright (C) 2015-2024 Free Software Foundation, Inc.
@@ -82,9 +82,8 @@ Written by Bruno Haible <bruno@clisp.org>, 2024.
-
+
+
diff --git a/gettext-tools/src/locating-rules.xsd b/gettext-tools/src/locating-rules.xsd10
similarity index 97%
rename from gettext-tools/src/locating-rules.xsd
rename to gettext-tools/src/locating-rules.xsd10
index 3bb86fd13..1795e6ea4 100644
--- a/gettext-tools/src/locating-rules.xsd
+++ b/gettext-tools/src/locating-rules.xsd10
@@ -2,7 +2,7 @@
- XML schema of *.loc files, as understood by GNU gettext.
+ XML schema 1.0 of *.loc files, as understood by GNU gettext.
Copyright (C) 2015-2024 Free Software Foundation, Inc.
diff --git a/gettext-tools/src/locating-rules.xsd11 b/gettext-tools/src/locating-rules.xsd11
new file mode 100644
index 000000000..d4bac98bb
--- /dev/null
+++ b/gettext-tools/src/locating-rules.xsd11
@@ -0,0 +1,87 @@
+
+
+
+
+ XML schema 1.1 of *.loc files, as understood by GNU gettext.
+
+Copyright (C) 2015-2024 Free Software Foundation, Inc.
+
+This file is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation, either version 3 of the License,
+or (at your option) any later version.
+
+This file is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+Written by Bruno Haible <bruno@clisp.org>, 2024.
+
+
+
+
+
+
+
+
+
+
+ Example:
+<locatingRules>
+ <locatingRule name="Glade" pattern="*.glade">
+ <documentRule localName="GTK-Interface" target="glade1.its"/>
+ <documentRule localName="glade-interface" target="glade2.its"/>
+ <documentRule localName="interface" target="gtkbuilder.its"/>
+ </locatingRule>
+ <locatingRule name="Glade" pattern="*.glade2">
+ <documentRule localName="glade-interface" target="glade2.its"/>
+ </locatingRule>
+ <locatingRule name="Glade" pattern="*.ui">
+ <documentRule localName="interface" target="gtkbuilder.its"/>
+ </locatingRule>
+</locatingRules>
+
+
+
+
+
+
+
+
+
+
+
+ Example:
+<locatingRule name="Glade" pattern="*.glade">
+ <documentRule localName="GTK-Interface" target="glade1.its"/>
+ <documentRule localName="glade-interface" target="glade2.its"/>
+ <documentRule localName="interface" target="gtkbuilder.its"/>
+</locatingRule>
+
+Note: An instance should not have both the 'target' attribute and a 'documentRule' child at the same time.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Example:
+<documentRule localName="GTK-Interface" target="glade1.its"/>
+
+
+
+
+
+
+