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:
@@ -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());
|
||||
|
||||
@@ -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"):
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user