Feature: s9api-basierte SaxonWorkerPool-Variante für XSLT 2.0/3.0
Die JAXP-basierte SaxonWorkerPool-Implementierung ist nur für XSLT 1.0 vollständig spezifiziert und kann bei XSLT 2.0/3.0 zu fehlerhaften Ausgaben führen. Änderungen: - Neue SaxonWorkerPoolS9Api-Klasse mit Saxon s9api für XSLT 2.0/3.0 - XsltVersion-Enum in conf.py (XSLT_1_0, XSLT_2_0_3_0) - ComboBox in Performance-Einstellungen zur XSLT-Version-Auswahl - MainWindow wählt automatisch richtige Worker-Pool-Variante - Verbesserte Classpath-Behandlung und Fehlerbehandlung Standard-Einstellung: XSLT 2.0/3.0 (s9api) - empfohlen für moderne Stylesheets Fallback: XSLT 1.0 (JAXP) - verfügbar für Legacy-Stylesheets 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
+14
-1
@@ -10,7 +10,7 @@ from ui.ApacheFopConfigDialog import ApacheFopConfigDialog
|
||||
from ui.XslDirConfigDialog import XslDirConfigDialog
|
||||
from ui.PostgreSqlConfigDialog import PostgreSqlConfigDialog
|
||||
from ui.PdfProject import PdfProjectDlg
|
||||
from conf import AppSettings, JavaVm, DiffPdf, SaxonJar, ApacheFop, XslDir, Project, PostgreSqlDb
|
||||
from conf import AppSettings, JavaVm, DiffPdf, SaxonJar, ApacheFop, XslDir, Project, PostgreSqlDb, XsltVersion
|
||||
|
||||
|
||||
class AppSettingsDlg(QDialog):
|
||||
@@ -282,6 +282,12 @@ class AppSettingsDlg(QDialog):
|
||||
# SaxonWorkerPool-Checkbox setzen
|
||||
self.ui.checkBoxUseSaxonPool.setChecked(self.settings.use_saxon_worker_pool)
|
||||
|
||||
# XSLT-Version ComboBox setzen
|
||||
if self.settings.saxon_xslt_version == XsltVersion.XSLT_1_0:
|
||||
self.ui.comboBoxXsltVersion.setCurrentIndex(0)
|
||||
else: # XSLT_2_0_3_0
|
||||
self.ui.comboBoxXsltVersion.setCurrentIndex(1)
|
||||
|
||||
# FopWorkerPool-Checkbox setzen
|
||||
self.ui.checkBoxUseFopPool.setChecked(self.settings.use_fop_worker_pool)
|
||||
|
||||
@@ -740,6 +746,13 @@ class AppSettingsDlg(QDialog):
|
||||
# Performance-Einstellungen übernehmen
|
||||
self.settings.max_workers = self.ui.spinBoxWorkerCount.value()
|
||||
self.settings.use_saxon_worker_pool = self.ui.checkBoxUseSaxonPool.isChecked()
|
||||
|
||||
# XSLT-Version übernehmen
|
||||
if self.ui.comboBoxXsltVersion.currentIndex() == 0:
|
||||
self.settings.saxon_xslt_version = XsltVersion.XSLT_1_0
|
||||
else:
|
||||
self.settings.saxon_xslt_version = XsltVersion.XSLT_2_0_3_0
|
||||
|
||||
self.settings.use_fop_worker_pool = self.ui.checkBoxUseFopPool.isChecked()
|
||||
|
||||
self.settings.save()
|
||||
|
||||
+64
-2
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>833</width>
|
||||
<height>446</height>
|
||||
<height>526</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -20,7 +20,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="elideMode">
|
||||
<enum>Qt::TextElideMode::ElideRight</enum>
|
||||
@@ -580,6 +580,55 @@ Deaktivieren Sie diese Option, wenn:
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayoutXsltVersion">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelXsltVersion">
|
||||
<property name="text">
|
||||
<string>XSLT-Version:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxXsltVersion">
|
||||
<property name="toolTip">
|
||||
<string>Wählen Sie die XSLT-Version für Saxon-Transformationen:
|
||||
|
||||
XSLT 1.0 (JAXP): Verwendet die JAXP Transformer API
|
||||
• Nur für XSLT 1.0 vollständig spezifiziert
|
||||
• Kann bei XSLT 2.0/3.0 zu fehlerhaften Ausgaben führen
|
||||
|
||||
XSLT 2.0/3.0 (s9api): Verwendet die Saxon s9api
|
||||
• Vollständige Unterstützung für XSLT 2.0 und 3.0
|
||||
• Empfohlen für moderne XSLT-Stylesheets</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>XSLT 1.0 (JAXP)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>XSLT 2.0/3.0 (s9api) - Empfohlen</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacerXsltVersion">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelSaxonPoolInfo">
|
||||
<property name="text">
|
||||
@@ -629,6 +678,19 @@ Deaktivieren Sie diese Option, wenn:
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="mouseTracking">
|
||||
|
||||
@@ -15,17 +15,17 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
|
||||
QFont, QFontDatabase, QGradient, QIcon,
|
||||
QImage, QKeySequence, QLinearGradient, QPainter,
|
||||
QPalette, QPixmap, QRadialGradient, QTransform)
|
||||
from PySide6.QtWidgets import (QAbstractButton, QApplication, QCheckBox, QDialog,
|
||||
QDialogButtonBox, QFrame, QGroupBox, QHBoxLayout,
|
||||
QHeaderView, QLabel, QPushButton, QSizePolicy,
|
||||
QSpacerItem, QSpinBox, QTabWidget, QTableWidget,
|
||||
QTableWidgetItem, QVBoxLayout, QWidget)
|
||||
from PySide6.QtWidgets import (QAbstractButton, QApplication, QCheckBox, QComboBox,
|
||||
QDialog, QDialogButtonBox, QFrame, QGroupBox,
|
||||
QHBoxLayout, QHeaderView, QLabel, QPushButton,
|
||||
QSizePolicy, QSpacerItem, QSpinBox, QTabWidget,
|
||||
QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget)
|
||||
|
||||
class Ui_Dialog(object):
|
||||
def setupUi(self, Dialog):
|
||||
if not Dialog.objectName():
|
||||
Dialog.setObjectName(u"Dialog")
|
||||
Dialog.resize(833, 446)
|
||||
Dialog.resize(833, 526)
|
||||
self.verticalLayout = QVBoxLayout(Dialog)
|
||||
self.verticalLayout.setObjectName(u"verticalLayout")
|
||||
self.tabSettings = QTabWidget(Dialog)
|
||||
@@ -336,6 +336,27 @@ class Ui_Dialog(object):
|
||||
|
||||
self.verticalLayout_11.addWidget(self.checkBoxUseSaxonPool)
|
||||
|
||||
self.horizontalLayoutXsltVersion = QHBoxLayout()
|
||||
self.horizontalLayoutXsltVersion.setObjectName(u"horizontalLayoutXsltVersion")
|
||||
self.labelXsltVersion = QLabel(self.groupBoxSaxonPool)
|
||||
self.labelXsltVersion.setObjectName(u"labelXsltVersion")
|
||||
|
||||
self.horizontalLayoutXsltVersion.addWidget(self.labelXsltVersion)
|
||||
|
||||
self.comboBoxXsltVersion = QComboBox(self.groupBoxSaxonPool)
|
||||
self.comboBoxXsltVersion.addItem("")
|
||||
self.comboBoxXsltVersion.addItem("")
|
||||
self.comboBoxXsltVersion.setObjectName(u"comboBoxXsltVersion")
|
||||
|
||||
self.horizontalLayoutXsltVersion.addWidget(self.comboBoxXsltVersion)
|
||||
|
||||
self.horizontalSpacerXsltVersion = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
|
||||
|
||||
self.horizontalLayoutXsltVersion.addItem(self.horizontalSpacerXsltVersion)
|
||||
|
||||
|
||||
self.verticalLayout_11.addLayout(self.horizontalLayoutXsltVersion)
|
||||
|
||||
self.labelSaxonPoolInfo = QLabel(self.groupBoxSaxonPool)
|
||||
self.labelSaxonPoolInfo.setObjectName(u"labelSaxonPoolInfo")
|
||||
self.labelSaxonPoolInfo.setWordWrap(True)
|
||||
@@ -363,6 +384,10 @@ class Ui_Dialog(object):
|
||||
|
||||
self.verticalLayout_9.addWidget(self.groupBoxFopPool)
|
||||
|
||||
self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
|
||||
|
||||
self.verticalLayout_9.addItem(self.verticalSpacer)
|
||||
|
||||
self.label = QLabel(self.tabPerformance)
|
||||
self.label.setObjectName(u"label")
|
||||
self.label.setMouseTracking(True)
|
||||
@@ -392,7 +417,7 @@ class Ui_Dialog(object):
|
||||
self.buttonBox.accepted.connect(Dialog.accept)
|
||||
self.buttonBox.rejected.connect(Dialog.reject)
|
||||
|
||||
self.tabSettings.setCurrentIndex(0)
|
||||
self.tabSettings.setCurrentIndex(7)
|
||||
|
||||
|
||||
QMetaObject.connectSlotsByName(Dialog)
|
||||
@@ -438,6 +463,21 @@ class Ui_Dialog(object):
|
||||
"\u2022 Sie die Funktion testen m\u00f6chten", None))
|
||||
#endif // QT_CONFIG(tooltip)
|
||||
self.checkBoxUseSaxonPool.setText(QCoreApplication.translate("Dialog", u"SaxonWorkerPool verwenden (empfohlen)", None))
|
||||
self.labelXsltVersion.setText(QCoreApplication.translate("Dialog", u"XSLT-Version:", None))
|
||||
self.comboBoxXsltVersion.setItemText(0, QCoreApplication.translate("Dialog", u"XSLT 1.0 (JAXP)", None))
|
||||
self.comboBoxXsltVersion.setItemText(1, QCoreApplication.translate("Dialog", u"XSLT 2.0/3.0 (s9api) - Empfohlen", None))
|
||||
|
||||
#if QT_CONFIG(tooltip)
|
||||
self.comboBoxXsltVersion.setToolTip(QCoreApplication.translate("Dialog", u"W\u00e4hlen Sie die XSLT-Version f\u00fcr Saxon-Transformationen:\n"
|
||||
"\n"
|
||||
"XSLT 1.0 (JAXP): Verwendet die JAXP Transformer API\n"
|
||||
"\u2022 Nur f\u00fcr XSLT 1.0 vollst\u00e4ndig spezifiziert\n"
|
||||
"\u2022 Kann bei XSLT 2.0/3.0 zu fehlerhaften Ausgaben f\u00fchren\n"
|
||||
"\n"
|
||||
"XSLT 2.0/3.0 (s9api): Verwendet die Saxon s9api\n"
|
||||
"\u2022 Vollst\u00e4ndige Unterst\u00fctzung f\u00fcr XSLT 2.0 und 3.0\n"
|
||||
"\u2022 Empfohlen f\u00fcr moderne XSLT-Stylesheets", None))
|
||||
#endif // QT_CONFIG(tooltip)
|
||||
self.labelSaxonPoolInfo.setText(QCoreApplication.translate("Dialog", u"<i>Hinweis: SaxonWorkerPool ben\u00f6tigt ein JDK (Java Development Kit).<br>Mit JRE allein werden Transformationen im Fallback-Modus ausgef\u00fchrt.</i>", None))
|
||||
self.groupBoxFopPool.setTitle(QCoreApplication.translate("Dialog", u"FopWorkerPool Einstellungen", None))
|
||||
#if QT_CONFIG(tooltip)
|
||||
|
||||
+26
-10
@@ -28,9 +28,10 @@ from ui.PdfProject import PdfProjectDlg
|
||||
from ui.TreeNodeEditDialog import TreeNodeEditDialog
|
||||
from ui.XslFileEditDialog import XslFileEditDialog
|
||||
from ui.XmlToXslAssignDialog import XmlToXslAssignDialog
|
||||
from conf import app_settings, Project, ProjectData, TreeNode, XslFile, XmlFile
|
||||
from conf import app_settings, Project, ProjectData, TreeNode, XslFile, XmlFile, XsltVersion
|
||||
from transform import TransformationJob, set_saxon_worker_pool
|
||||
from saxon_pool import SaxonWorkerPool
|
||||
from saxon_pool_s9api import SaxonWorkerPoolS9Api
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@@ -727,22 +728,37 @@ class MainWindow(QMainWindow):
|
||||
logger.warning("Java VM oder Saxon JAR nicht gefunden, Pool nicht initialisiert")
|
||||
return
|
||||
|
||||
# Erstelle Worker-Pool
|
||||
# Erstelle Worker-Pool (wähle richtige Variante basierend auf XSLT-Version)
|
||||
num_workers = app_settings.max_workers
|
||||
log_dir = self.project.project_dir / "temp"
|
||||
pool = SaxonWorkerPool(
|
||||
num_workers=num_workers,
|
||||
java_vm_path=java_vm.path_to_binary_file,
|
||||
saxon_jar_path=saxon_jar.path_to_jar_file,
|
||||
classpath_cache=TransformationJob._classpath_cache,
|
||||
log_dir=log_dir,
|
||||
)
|
||||
|
||||
# Wähle die richtige Worker-Pool-Implementierung
|
||||
if app_settings.saxon_xslt_version == XsltVersion.XSLT_1_0:
|
||||
# JAXP-basierte Variante für XSLT 1.0
|
||||
pool = SaxonWorkerPool(
|
||||
num_workers=num_workers,
|
||||
java_vm_path=java_vm.path_to_binary_file,
|
||||
saxon_jar_path=saxon_jar.path_to_jar_file,
|
||||
classpath_cache=TransformationJob._classpath_cache,
|
||||
log_dir=log_dir,
|
||||
)
|
||||
pool_type = "JAXP (XSLT 1.0)"
|
||||
else:
|
||||
# s9api-basierte Variante für XSLT 2.0/3.0
|
||||
pool = SaxonWorkerPoolS9Api(
|
||||
num_workers=num_workers,
|
||||
java_vm_path=java_vm.path_to_binary_file,
|
||||
saxon_jar_path=saxon_jar.path_to_jar_file,
|
||||
classpath_cache=TransformationJob._classpath_cache,
|
||||
log_dir=log_dir,
|
||||
)
|
||||
pool_type = "s9api (XSLT 2.0/3.0)"
|
||||
|
||||
# Setze globalen Pool
|
||||
set_saxon_worker_pool(pool)
|
||||
|
||||
logger.info(
|
||||
f"Saxon-Worker-Pool initialisiert: {num_workers} Worker "
|
||||
f"Saxon-Worker-Pool initialisiert: {num_workers} Worker mit {pool_type} "
|
||||
f"(erwartet: {num_workers}x schneller für Saxon-Transformationen)"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user