1
0
mirror of https://github.com/alexandrev/xslt-lab.git synced 2026-09-13 08:43:16 +00:00
claude-code 4e1f3ffdac Fix: give the backend room to run, and stop transforming half-typed expressions
The backend container runs three JVMs — Saxon 12, Saxon 9.6 and Xalan — whose
-Xmx values add up to 512 MB, inside a container limited to 256Mi. The limit was
half the heap the JVMs believed they had, so the kernel was killing the
container: OOMKilled twice a day on the 16th and 17th of August, five times a
day on the 18th and 19th, and 81 users in 24 hours got "transform service
unavailable" instead of a result. Before each kill the serial collector spends
hours in continuous full GC, which is why three of the five pods sat pinned at
exactly 0.5 CPU — their limit — around the clock, and why XSLT 2.0's p95 was
5.5s against 0.7s for the other two engines.

Those limits were never in the chart to begin with: the backend deployment has
never rendered a resources block, values.resources.backend was declared and
unused, and the live numbers came from a manual kubectl patch that an ArgoCD
sync would have silently dropped. So the chart now owns them, with room for
what actually runs in there. The CPU request moves 10m -> 250m as well: against
real usage of 500m the HPA read utilisation in the thousands of percent and the
deployment sat permanently at maxReplicas, unable to signal anything. And the
backend gets minReplicas 2, for the reason the frontend already learnt.

The other half is the mid-keystroke problem again, one level down. Gating the
automatic run on well-formedness took the error rate from 54% to 24%, but a
stylesheet whose XPath is half-typed is perfectly good XML, so it still went to
the backend and still came back as a compile error. A day of logs is mostly
that, keystroke by keystroke: 'current()/..[@N' then '[@Na' then '[@Name', and
"Required attribute 'select' is missing" 65 times on a single line. So the gate
now also declines to send an expression that is provably unfinished — a
required attribute that is absent, an empty value, a quote or bracket still
open, a trailing token that cannot end an expression. Facts about the text, not
guesses at intent: there are twice as many tests for what it must leave alone
as for what it catches, including every template the app itself ships. It is
skipped above 64KB, where a document was pasted rather than typed, and as
before it only holds back the automatic run — "Run it anyway" is always there.

Finally, the error classifier learns the rest of what was sitting in "other":
Xalan's "Syntax error in '<expr>'" is the stylesheet's XPath, not the input.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HnUwBeXv6PCTEzRpFoMSU
2026-08-19 19:30:02 +00:00
2025-11-15 22:26:25 +01:00
2026-01-27 13:10:36 +01:00
2025-11-15 22:26:25 +01:00
2025-07-01 21:35:11 +02:00
2025-11-15 22:26:25 +01:00

XSLT Playground — free online XSLT 1.0/2.0/3.0 tester & editor (Saxon HE)

Live tool: xsltplayground.com · Blog: xsltplayground.com/blog

XSLT Playground is a free online XSLT editor, tester and validator that runs XSLT 1.0, 2.0 and 3.0 on a real Saxon HE 12.5 backend — the same processor used in production integration pipelines. No install, no signup. Unlike browser-only (Saxon-JS) tools, it executes server-side Saxon HE, so results match production behaviour, including full XSLT 3.0: maps, arrays, xsl:merge, higher-order functions, streaming and JSON output.

What makes it useful for real-world XSLT work:

  • XSLT 1.0, 2.0 and 3.0 via Saxon HE 12.5 (real server-side processor)
  • Multiple XML inputs passed as named parameters — like a production pipeline
  • Execution trace to debug stylesheets step by step
  • Validation with exact line-number error messages from Saxon
  • Up to 3 independent workspaces, export/import as JSON to share setups
  • Custom Saxon extension functions (tib:uuid(), tib:timestamp(), …)

Built for integration engineers working with enterprise middleware (SAP, MuleSoft, Tibco, IBM), XML data engineers, and anyone who needs to write or debug XSLT without a heavy desktop IDE.

This repository hosts the source: a React/Vite frontend and a Go backend that orchestrates Java/Saxon. Suggested GitHub topics: xslt, xslt-3-0, saxon, xml, online-tool, xslt-editor, xslt-tester.

TinyLaunch Badge

News & Releases

Frontend

The React/Vite frontend lives in frontend/. Use npm install inside that folder and run:

npm run dev

This starts the playground at http://localhost:3000.

The app will call the Go backend at /transform to perform XSLT transformations. Set the backend URL by creating a .env file inside frontend/ or by exporting VITE_BACKEND_URL when starting the dev server:

VITE_BACKEND_URL=http://localhost:8000 npm run dev

If omitted the app assumes the backend runs on the same host and port. In the containerized version the URL is now read at runtime from environment variables so you can configure it directly in the pod.

When VITE_GO_PRO=true the UI exposes additional features like Google authentication. For authentication you must provide Firebase configuration via VITE_FIREBASE_CONFIG containing the JSON object used by initializeApp. Set VITE_GA_ID to enable Google Analytics tracking.

The playground keeps up to three independent workspaces (tabs). Each workspace persists its own inputs, trace output, errors and results, and you can export or import them as JSON files to share setups easily.

Docker

To build a container with the compiled frontend run:

docker build -t xslt-playground-frontend frontend

The resulting image serves the static files with nginx on port 80. When the container starts it logs the value of VITE_BACKEND_URL so you can confirm the backend in use in the pod logs. The URL is now picked up at runtime from the container environment.

Using this URL as backendURL: http://localhost:8000

Backend

The Go backend resides under backend/. Compile it using the Makefile which downloads Go modules automatically:

make backend-build
./backend/server

You can also produce a container image using the provided Dockerfile:

docker build -t xslt-playground-backend backend

By default it listens on port 8000 as configured in backend/app.config. The same file sets saxon_classpath so the Java process can load Saxon and its dependencies from /opt/saxon/*.

The backend image also builds a small jar with custom Saxon extension functions. It gets copied to /opt/saxon/custom-functions.jar during the Docker build. You can call these from XSLT using the namespace xmlns:tib="http://www.tibco.com/bw/xslt/custom-functions". The jar exposes many helper functions such as tib:uuid(), tib:timestamp() and tib:addToDate().

Environment

When VITE_GO_PRO=true the backend stores transformation history and requires a PostgreSQL database as well as Firebase credentials for authentication. Provide these via environment variables:

export DATABASE_URL="postgres://user:pass@localhost/dbname"
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/serviceAccount.json
export SAXON_CLASSPATH=/opt/saxon/*

The Firebase project ID is read from the credentials file.

If VITE_GO_PRO is not set or is false the backend skips database and Firebase initialization and only exposes the /transform endpoint.

Makefile

Common tasks are defined in the provided Makefile. Running make without arguments will build both binaries, create the container images and start Docker Compose without shutting it down automatically:

# Build Go binary
make backend-build
# Build React production files
make frontend-build
# Create container images
make backend-image
make frontend-image

Docker Compose

To run the entire stack locally with PostgreSQL use:

make backend-image frontend-image
docker compose up

For a lightweight setup without PostgreSQL run:

docker compose -f docker-compose.local.yml up

This starts just the frontend and backend with VITE_GO_PRO=false.

The compose file passes VITE_BACKEND_URL=http://backend:8000 to the frontend container so it talks to the backend container.

This starts the backend on port 8000, the frontend on 3000 and a PostgreSQL instance on 5432.

Helm Chart

A Helm chart is provided under charts/xslt-playground to deploy the frontend and backend on Kubernetes. By default it expects Firebase credentials and a PostgreSQL database. Before installing, create a secret with your Firebase credentials:

kubectl create secret generic firebase-config \
  --from-file=service-account.json=</path/to/serviceAccount.json> \
  --from-file=firebase-config.json=</path/to/firebaseConfig.json>

Install the chart with:

helm install xslt charts/xslt-playground
# Disable Firebase or database support if desired
# helm install xslt charts/xslt-playground --set firebase.enabled=false
# helm install xslt charts/xslt-playground --set storage.enabled=false
S
Description
Mirror de solo lectura de github.com/alexandrev/xslt-lab — el origen, los issues y el despliegue siguen en GitHub
https://github.com/alexandrev/xslt-lab
Readme 12 MiB
Languages
JavaScript 34.8%
Java 23.2%
HTML 19.9%
CSS 8.7%
Go 6.7%
Other 6.6%