1
0
mirror of https://github.com/alexandrev/xslt-lab.git synced 2026-09-13 08:43:16 +00:00

Fix: stop rejecting valid enterprise stylesheets, and classify the rest of "other"

Three things the error review turned up.

Secure processing caps an XPath expression at 100 operators, so the JDK was
refusing perfectly valid stylesheets with JAXP0801002 — a limit this service
imposes, not a mistake by the author. The XSLT 1.0 daemon now raises the op,
group and total limits instead of switching secure processing off, which also
guards external entity access; a runaway expression is still bounded by the
10s transform timeout, and any -D on the command line still wins.

That error is now classified as "backend" rather than "stylesheet": it belongs
with the bug candidates, not with user error, or the dashboard hides it.

The remaining unclassified errors were mostly classifiable all along, and the
patterns come straight from the production logs: multiply-defined and
undefined variables, format-number picture strings and missing Java extension
methods are the author's stylesheet; a stray <?xml ...?> declaration is the
input document.

Finally, calls to Java extension methods now say so: the playground runs stock
Saxon HE, so a class from the author's own project or their ESB runtime will
never resolve, and the raw "Cannot find external method" gives no clue why.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KZntQUfw463NW4ftgSjWw5
This commit is contained in:
2026-08-03 09:43:31 +00:00
parent 3925ed9e77
commit 053a7d95e5
4 changed files with 49 additions and 0 deletions
@@ -25,6 +25,17 @@ public class XalanDaemon {
System.setProperty("javax.xml.transform.TransformerFactory",
"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
// Secure processing caps an XPath expression at 100 operators, and real
// enterprise stylesheets go past it — users were getting JAXP0801002
// ("exceeds the '100' limit set by FEATURE_SECURE_PROCESSING") on
// stylesheets that are perfectly valid. Raise the limits rather than
// turning secure processing off, which also guards external entity
// access; runaway expressions are already bounded by the 10s transform
// timeout. 0 would mean no limit at all, so keep a generous ceiling.
setIfAbsent("jdk.xml.xpathExprOpLimit", "10000");
setIfAbsent("jdk.xml.xpathExprGrpLimit", "1000");
setIfAbsent("jdk.xml.xpathTotalOpLimit", "1000000");
// Warm up
try {
TransformerFactory.newInstance().newTemplates(new StreamSource(new StringReader(
@@ -36,6 +47,13 @@ public class XalanDaemon {
System.out.println("XalanDaemon: warm-up complete.");
}
/** Leaves any value supplied on the command line (-D...) untouched. */
private static void setIfAbsent(String key, String value) {
if (System.getProperty(key) == null) {
System.setProperty(key, value);
}
}
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress("127.0.0.1", PORT), 32);
server.createContext("/transform", new TransformHandler());
+14
View File
@@ -151,6 +151,8 @@ func classifyTransformError(msg string) (code, class string) {
"the markup in the document",
"content of elements must consist",
"must be followed by either attribute",
// An <?xml ...?> declaration anywhere but the very start of the document.
"processing instruction target matching",
}
// Stylesheet-authoring failures. Saxon reports many of these without a code
// prefix; Xalan/JAXP (XSLT 1.0) reports undefined functions, misplaced
@@ -164,9 +166,21 @@ func classifyTransformError(msg string) (code, class string) {
"cannot convert data-type",
"error checking type of the expression",
"transformerconfigurationexception",
// Seen in production sitting in "other": all of them are the author's
// stylesheet, not the input document.
"is multiply defined",
"is undefined",
"format-number picture",
"cannot find external method",
}
switch {
// A platform limit we impose, not a mistake in the user's stylesheet, so it
// must not be filed under "stylesheet" where it would look like user error.
case strings.Contains(lower, "jaxp0801002") ||
strings.Contains(lower, "feature_secure_processing"):
class = "backend"
code = "XPATH_OP_LIMIT"
// No source document supplied. Saxon phrases this with spaces ("an initial
// template"), so the hyphenated initial-template check below never caught it.
case strings.Contains(lower, "initial template or an initial function"):
+8
View File
@@ -229,6 +229,14 @@ func TestClassifyTransformError(t *testing.T) {
{"xalan illegal attr", "line 242: Illegal attribute 'select'.", "stylesheet", "COMPILE"},
{"xalan 2.0 fn in 1.0", "Error checking type of the expression 'funcall(current-date, [])'.", "stylesheet", "COMPILE"},
{"no source document", "Either a source document, an initial template or an initial function must be specified", "input_xml", "NO_SOURCE"},
// Previously all of these fell into "other"; taken from production logs.
{"multiply defined variable", "line 11: Variable 'DestinationCode' is multiply defined in the same scope.", "stylesheet", "COMPILE"},
{"undefined variable", "line 42: Variable or parameter 'OriginCode' is undefined.", "stylesheet", "COMPILE"},
{"format-number picture", "format-number picture: Passive character must not appear between active characters in a sub-picture", "stylesheet", "COMPILE"},
{"missing java extension", "Cannot find external method 'com.example.util.DateUtil.now' (must be public).", "stylesheet", "COMPILE"},
{"stray xml declaration", `The processing instruction target matching "[xX][mM][lL]" is not allowed.`, "input_xml", "PARSE"},
// A limit the service imposes — a bug candidate, not the user's mistake.
{"xpath operator limit", "JAXP0801002: the compiler encountered an XPath expression containing '101' operators that exceeds the '100' limit set by 'FEATURE_SECURE_PROCESSING'.", "backend", "XPATH_OP_LIMIT"},
{"truly unknown", "some unexpected failure", "other", "OTHER"},
}
for _, c := range cases {
+9
View File
@@ -2721,6 +2721,15 @@ export default function App() {
</button>
</p>
)}
{/Cannot find external method|Could not find function.*:[a-zA-Z]|external function/i.test(error) && (
<p className="error-doc-hint">
💡 This stylesheet calls a Java extension method. The playground runs
stock Saxon HE, so classes from your own project (or your ESB's
runtime) are not on its classpath. Replace the call with standard
XPath, or stub the value out with an <code>xsl:param</code> to test
the rest of the transform here.
</p>
)}
{(() => {
const ref = findErrorReference(error);
if (!ref) return null;