Révision 1384
| tmp/org.txm.groovy.core/src/groovy/org/txm/macro/xml/CombineNumberElementMacro.groovy (revision 1384) | ||
|---|---|---|
| 1 |
// Copyright © 2018 ENS de Lyon, CNRS, University of Franche-Comté |
|
| 2 |
// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses) |
|
| 3 |
// @author sheiden |
|
| 4 |
|
|
| 5 |
/* |
|
| 6 |
|
|
| 7 |
This macro calls NumberElement successively |
|
| 8 |
|
|
| 9 |
*/ |
|
| 10 |
|
|
| 11 |
package org.txm.macro.xml |
|
| 12 |
|
|
| 13 |
res = gse.run(NumberElementMacro, [ |
|
| 14 |
"args":[ |
|
| 15 |
"inputDirectory":new File("/home/sheiden/Documents/projet-susana-mars-reers/corpus/tei"),
|
|
| 16 |
"outputDirectory":new File("/home/sheiden/Documents/projet-susana-mars-reers/corpus/tei/out"),
|
|
| 17 |
"elementName":"pb", |
|
| 18 |
"elementAttribute":"n", |
|
| 19 |
"countStart":94, |
|
| 20 |
"valuePrefix":"", |
|
| 21 |
"valueSuffix":"", |
|
| 22 |
"debug":"true" |
|
| 23 |
], |
|
| 24 |
"selection":selection, |
|
| 25 |
"selections":selections, |
|
| 26 |
"corpusViewSelection":corpusViewSelection, |
|
| 27 |
"corpusViewSelections":corpusViewSelections, |
|
| 28 |
"monitor":monitor]) |
|
| 29 |
if (!res) println "** problem calling NumberElementMacro." |
|
| 30 |
|
|
| 31 |
res = gse.run(NumberElementMacro, [ |
|
| 32 |
"args":["inputDirectory":new File("/home/sheiden/Documents/projet-susana-mars-reers/corpus/tei/out"),
|
|
| 33 |
"outputDirectory":new File("/home/sheiden/Documents/projet-susana-mars-reers/corpus/tei/out/out"),
|
|
| 34 |
"elementName":"pb", |
|
| 35 |
"elementAttribute":"facs", |
|
| 36 |
"countStart":102, |
|
| 37 |
"valuePrefix":"https://gallica.bnf.fr/iiif/ark:/12148/bpt6k35936/f", |
|
| 38 |
"valueSuffix":"/full/full/0/native.jpg", |
|
| 39 |
"debug":"true" |
|
| 40 |
], |
|
| 41 |
"selection":selection, |
|
| 42 |
"selections":selections, |
|
| 43 |
"corpusViewSelection":corpusViewSelection, |
|
| 44 |
"corpusViewSelections":corpusViewSelections, |
|
| 45 |
"monitor":monitor]) |
|
| 46 |
if (!res) println "** problem calling NumberElementMacro." |
|
| 47 |
|
|
| tmp/org.txm.groovy.core/src/groovy/org/txm/macro/xml/IndentMacro.groovy (revision 1384) | ||
|---|---|---|
| 1 |
package org.txm.macro.xml |
|
| 2 |
// STANDARD DECLARATIONS |
|
| 3 |
|
|
| 4 |
import org.kohsuke.args4j.* |
|
| 5 |
import groovy.transform.Field |
|
| 6 |
import org.txm.rcpapplication.swt.widget.parameters.* |
|
| 7 |
import org.txm.importer.ApplyXsl2 |
|
| 8 |
|
|
| 9 |
// BEGINNING OF PARAMETERS |
|
| 10 |
|
|
| 11 |
@Field @Option(name="inputDirectory", usage="an example folder", widget="Folder", required=true, def="in") |
|
| 12 |
def inputDirectory = new File(System.getProperty("user.home"),"/tmp/xsltest")
|
|
| 13 |
|
|
| 14 |
@Field @Option(name="outputDirectory", usage="an example folder", widget="Folder", required=true, def="out") |
|
| 15 |
def outputDirectory = new File("/tmp/xsltest/out")
|
|
| 16 |
|
|
| 17 |
@Field @Option(name="omitXmlDeclaration", usage="omit xml declaration", widget="Boolean", required=false, def="false") |
|
| 18 |
def omitXmlDeclaration |
|
| 19 |
|
|
| 20 |
@Field @Option(name="suppressIndentation", usage="space delimited list of elements not to indent", widget="Text", required=false, def="") |
|
| 21 |
def suppressIndentation |
|
| 22 |
|
|
| 23 |
@Field @Option(name="doubleSpace", usage="space delimited list of elements with forced line break before", widget="Text", required=false, def="") |
|
| 24 |
def doubleSpace |
|
| 25 |
|
|
| 26 |
@Field @Option(name="encoding", usage="output character encoding", widget="String", required=false, def="utf-8") |
|
| 27 |
def encoding |
|
| 28 |
|
|
| 29 |
@Field @Option(name="namespacesDeclaration", usage="space delimited list of namespace declarations (eg \"xmlns:dc='http://purl.org/dc/elements/1.1/'\")", widget="Text", required=false, def="") |
|
| 30 |
def namespacesDeclaration |
|
| 31 |
|
|
| 32 |
@Field @Option(name="debug", usage="Show debug messages", widget="Boolean", required=true, def="false") |
|
| 33 |
def debug |
|
| 34 |
|
|
| 35 |
if (!ParametersDialog.open(this)) return |
|
| 36 |
|
|
| 37 |
// END OF PARAMETERS |
|
| 38 |
|
|
| 39 |
doubleSpace = doubleSpace.trim() |
|
| 40 |
|
|
| 41 |
if (doubleSpace.length() > 0) doubleSpace = " saxon:double-space=\"$doubleSpace\"" |
|
| 42 |
|
|
| 43 |
suppressIndentation = suppressIndentation.trim() |
|
| 44 |
|
|
| 45 |
if (suppressIndentation.length() > 0) suppressIndentation = " saxon:suppress-indentation=\"$suppressIndentation\"" |
|
| 46 |
|
|
| 47 |
encoding = encoding.trim() |
|
| 48 |
|
|
| 49 |
if (encoding.length() > 0) encoding = " encoding=\"$encoding\"" |
|
| 50 |
|
|
| 51 |
if (omitXmlDeclaration) omitXmlDeclarationP = " omit-xml-declaration=\"yes\"" else omitXmlDeclarationP = " omit-xml-declaration=\"no\"" |
|
| 52 |
|
|
| 53 |
namespacesDeclaration = namespacesDeclaration.trim() |
|
| 54 |
|
|
| 55 |
if (namespacesDeclaration.length() > 0) namespacesDeclaration = " $namespacesDeclaration" |
|
| 56 |
|
|
| 57 |
def xslParameters = "" |
|
| 58 |
|
|
| 59 |
IndentStyleSheet = """ |
|
| 60 |
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://saxon.sf.net/"${namespacesDeclaration}>
|
|
| 61 |
<xsl:output method="xml" indent="yes"${omitXmlDeclarationP}${encoding}${doubleSpace}${suppressIndentation}/>
|
|
| 62 |
<!-- saxon:indent-spaces="6" for Saxon-PE only --> |
|
| 63 |
<xsl:template match="node()|@*"> |
|
| 64 |
<xsl:copy> |
|
| 65 |
<!-- Including any attributes it has and any child nodes --> |
|
| 66 |
<xsl:apply-templates select="@*|node()"/> |
|
| 67 |
</xsl:copy> |
|
| 68 |
</xsl:template> |
|
| 69 |
</xsl:stylesheet>""" |
|
| 70 |
|
|
| 71 |
def XSLFile = File.createTempFile("IndentStyleSheet",".xsl")
|
|
| 72 |
XSLFile.deleteOnExit() |
|
| 73 |
|
|
| 74 |
XSLFile << IndentStyleSheet |
|
| 75 |
|
|
| 76 |
outputDirectory.mkdir() |
|
| 77 |
|
|
| 78 |
xslParameters = xslParameters.trim() |
|
| 79 |
if (xslParameters.length() == 0) {
|
|
| 80 |
xslParameters = null |
|
| 81 |
} else {
|
|
| 82 |
def split = xslParameters.split("\n")
|
|
| 83 |
xslParameters = [] |
|
| 84 |
for (def str : split) {
|
|
| 85 |
def split2 = str.split("=", 2)
|
|
| 86 |
if (split2.size() == 2) {
|
|
| 87 |
xslParameters << split2 |
|
| 88 |
} |
|
| 89 |
} |
|
| 90 |
} |
|
| 91 |
|
|
| 92 |
println "Processed directory: $inputDirectory." |
|
| 93 |
|
|
| 94 |
def files = [] |
|
| 95 |
ApplyXsl2 a = new ApplyXsl2(XSLFile.getAbsolutePath()) |
|
| 96 |
inputDirectory.eachFileMatch(~/.+\.(xml|XML)/) { XMLFile ->
|
|
| 97 |
String name = XMLFile.getName() |
|
| 98 |
try {
|
|
| 99 |
|
|
| 100 |
def outFile = new File(outputDirectory, name) |
|
| 101 |
if (xslParameters != null) {
|
|
| 102 |
for(def param : xslParameters) {
|
|
| 103 |
a.setParam(param[0], param[1]) |
|
| 104 |
} |
|
| 105 |
} |
|
| 106 |
a.process(XMLFile, outFile) |
|
| 107 |
a.resetParams() |
|
| 108 |
files << XMLFile |
|
| 109 |
} catch (Exception e) {
|
|
| 110 |
|
|
| 111 |
msgParse = (e.getMessageAndLocation() =~ /^(.*) lineNumber: ([0-9]+); columnNumber: ([0-9]+); (.*).$/) |
|
| 112 |
if (msgParse.size() == 1) {
|
|
| 113 |
|
|
| 114 |
def lineNumber = msgParse[0][2] |
|
| 115 |
def colNumber = msgParse[0][3] |
|
| 116 |
def errMsg = msgParse[0][4] |
|
| 117 |
|
|
| 118 |
println "** $name processing aborted, [line $lineNumber, character $colNumber]: $errMsg." |
|
| 119 |
|
|
| 120 |
|
|
| 121 |
} else {
|
|
| 122 |
println e.getMessageAndLocation() |
|
| 123 |
} |
|
| 124 |
|
|
| 125 |
XSLFile.delete() |
|
| 126 |
return 0 |
|
| 127 |
} |
|
| 128 |
} |
|
| 129 |
|
|
| 130 |
XSLFile.delete() |
|
| 131 |
|
|
| 132 |
return 1 |
|
| 133 |
|
|
| tmp/org.txm.groovy.core/src/groovy/org/txm/macro/xml/ValidateMacro.groovy (revision 1384) | ||
|---|---|---|
| 1 |
// Copyright © 2018 ENS de Lyon, CNRS, University of Franche-Comté |
|
| 2 |
// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses) |
|
| 3 |
// @author sheiden |
|
| 4 |
|
|
| 5 |
package org.txm.macro.xml |
|
| 6 |
|
|
| 7 |
// STANDARD DECLARATIONS |
|
| 8 |
|
|
| 9 |
import java.nio.file.Files |
|
| 10 |
|
|
| 11 |
import org.kohsuke.args4j.* |
|
| 12 |
import groovy.transform.Field |
|
| 13 |
import org.txm.rcpapplication.commands.* |
|
| 14 |
import org.txm.rcpapplication.swt.widget.parameters.* |
|
| 15 |
import org.txm.importer.ApplyXsl2 |
|
| 16 |
|
|
| 17 |
import net.sf.saxon.TransformerFactoryImpl |
|
| 18 |
import org.txm.utils.saxon.SaxonNodeSet |
|
| 19 |
import javax.xml.transform.stream.StreamSource |
|
| 20 |
import javax.xml.transform.stream.StreamResult |
|
| 21 |
|
|
| 22 |
import org.eclipse.core.filesystem.EFS |
|
| 23 |
import org.eclipse.ui.PlatformUI |
|
| 24 |
import org.eclipse.ui.ide.IDE |
|
| 25 |
import org.eclipse.jface.text.ITextOperationTarget |
|
| 26 |
|
|
| 27 |
// BEGINNING OF PARAMETERS |
|
| 28 |
|
|
| 29 |
@Field @Option(name="inputDirectory", usage="an example folder", widget="Folder", required=true, def="in") |
|
| 30 |
def inputDirectory = new File(System.getProperty("user.home"),"/tmp/xsltest")
|
|
| 31 |
|
|
| 32 |
@Field @Option(name="edit", usage="edit XML files with errors", widget="Boolean", required=true, def="true") |
|
| 33 |
def edit |
|
| 34 |
|
|
| 35 |
@Field @Option(name="maxEditors", usage="maximum number of files opened", widget="Integer", required=true, def="4") |
|
| 36 |
def maxEditors |
|
| 37 |
|
|
| 38 |
@Field @Option(name="debug", usage="Show debug messages", widget="Boolean", required=true, def="false") |
|
| 39 |
def debug |
|
| 40 |
|
|
| 41 |
if (!ParametersDialog.open(this)) return |
|
| 42 |
|
|
| 43 |
// END OF PARAMETERS |
|
| 44 |
|
|
| 45 |
def xslParameters = "" |
|
| 46 |
def nEditors = 0 |
|
| 47 |
|
|
| 48 |
IdentityStyleSheet = """ |
|
| 49 |
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://saxon.sf.net/"> |
|
| 50 |
<xsl:output method="xml"/> |
|
| 51 |
<xsl:template match="node()|@*"> |
|
| 52 |
<xsl:copy> |
|
| 53 |
<xsl:apply-templates select="@*|node()"/> |
|
| 54 |
</xsl:copy> |
|
| 55 |
</xsl:template> |
|
| 56 |
</xsl:stylesheet>""" |
|
| 57 |
|
|
| 58 |
def XSLFile = File.createTempFile("IdentityStyleSheet",".xsl")
|
|
| 59 |
XSLFile.deleteOnExit() |
|
| 60 |
addShutdownHook {
|
|
| 61 |
XSLFile.delete() |
|
| 62 |
println XSLFile+" deleted." |
|
| 63 |
} |
|
| 64 |
|
|
| 65 |
XSLFile << IdentityStyleSheet |
|
| 66 |
|
|
| 67 |
def outputDirectory = Files.createTempDirectory("Validate")
|
|
| 68 |
outputDirectory = outputDirectory.toFile() |
|
| 69 |
outputDirectory.deleteOnExit() |
|
| 70 |
|
|
| 71 |
xslParameters = xslParameters.trim() |
|
| 72 |
if (xslParameters.length() == 0) {
|
|
| 73 |
xslParameters = null |
|
| 74 |
} else {
|
|
| 75 |
def split = xslParameters.split("\n")
|
|
| 76 |
xslParameters = [] |
|
| 77 |
for (def str : split) {
|
|
| 78 |
def split2 = str.split("=", 2)
|
|
| 79 |
if (split2.size() == 2) {
|
|
| 80 |
xslParameters << split2 |
|
| 81 |
} |
|
| 82 |
} |
|
| 83 |
} |
|
| 84 |
|
|
| 85 |
println "Processed directory: $inputDirectory." |
|
| 86 |
|
|
| 87 |
// let's build a Saxon XSLT processor |
|
| 88 |
|
|
| 89 |
System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl")
|
|
| 90 |
tFactory = new net.sf.saxon.TransformerFactoryImpl() |
|
| 91 |
tConfiguration = tFactory.getConfiguration() |
|
| 92 |
tConfiguration.registerExtensionFunction(new SaxonNodeSet()) // ? |
|
| 93 |
// the following features don't seem to work, yet |
|
| 94 |
tConfiguration.setConfigurationProperty(net.sf.saxon.lib.FeatureKeys.LINE_NUMBERING, true) |
|
| 95 |
tConfiguration.setConfigurationProperty(net.sf.saxon.lib.FeatureKeys.RECOVERY_POLICY, net.sf.saxon.Configuration.RECOVER_WITH_WARNINGS) |
|
| 96 |
|
|
| 97 |
// === TODO: other configuration tuning options === |
|
| 98 |
// Basically: |
|
| 99 |
// - schema validation |
|
| 100 |
// - dtd validation |
|
| 101 |
// - etc. |
|
| 102 |
// |
|
| 103 |
// DTD_VALIDATION |
|
| 104 |
// DTD_VALIDATION_RECOVERABLE |
|
| 105 |
// LINE_NUMBERING |
|
| 106 |
// RECOVERY_POLICY: Configuration.RECOVER_SILENTLY, Configuration.RECOVER_WITH_WARNINGS, or Configuration.DO_NOT_RECOVER. |
|
| 107 |
// RECOVERY_POLICY_NAME (get?) |
|
| 108 |
// SCHEMA_VALIDATION |
|
| 109 |
// SCHEMA_VALIDATION_MODE: None, Strict, Lax, Preserve |
|
| 110 |
// STANDARD_ERROR_OUTPUT_FILE |
|
| 111 |
// STRIP_WHITESPACE |
|
| 112 |
// SUPPRESS_XSLT_NAMESPACE_CHECK |
|
| 113 |
// TRACE_LISTENER |
|
| 114 |
// VALIDATION_COMMENTS |
|
| 115 |
// VALIDATION_WARNINGS |
|
| 116 |
// XSD_VERSION |
|
| 117 |
// XSLT_SCHEMA_AWARE |
|
| 118 |
|
|
| 119 |
def transformer = tFactory.newTransformer(new StreamSource(XSLFile)) |
|
| 120 |
|
|
| 121 |
inputDirectory.eachFileMatch(~/.+\.(xml|XML)/) { xmlInputFile ->
|
|
| 122 |
name = xmlInputFile.getName() |
|
| 123 |
def editor = "" |
|
| 124 |
try {
|
|
| 125 |
|
|
| 126 |
def xmlOutputFile = new File(outputDirectory, name) |
|
| 127 |
xmlOutputFile.deleteOnExit() |
|
| 128 |
|
|
| 129 |
try {
|
|
| 130 |
|
|
| 131 |
// redirect XSLT processor error output |
|
| 132 |
tmperr = new ByteArrayOutputStream() |
|
| 133 |
tFactory.getErrorListener().setErrorOutput(new PrintStream(tmperr)) |
|
| 134 |
|
|
| 135 |
strWriter = new StringWriter() |
|
| 136 |
out = new StreamResult(strWriter) |
|
| 137 |
|
|
| 138 |
transformer.transform(new StreamSource(xmlInputFile), out) |
|
| 139 |
|
|
| 140 |
if (debug) println "stderr = "+tmperr.toString(java.nio.charset.StandardCharsets.UTF_8) |
|
| 141 |
//System.setErr(stderr) |
|
| 142 |
|
|
| 143 |
w = new BufferedWriter(new FileWriter(xmlOutputFile)) |
|
| 144 |
w.write(strWriter.toString()) |
|
| 145 |
w.close() |
|
| 146 |
|
|
| 147 |
// reset transformer to free memory |
|
| 148 |
transformer = tFactory.newTransformer(new StreamSource(XSLFile)) |
|
| 149 |
|
|
| 150 |
} catch (Exception e) {
|
|
| 151 |
|
|
| 152 |
// org.xml.sax.SAXParseException; systemId: file:/home/sheiden/Documents/txm/xml/sample.xml; lineNumber: 3; columnNumber: 1; Le type d'élément "a" doit être suivi des spécifications d'attribut, ">" ou "/>". |
|
| 153 |
|
|
| 154 |
msgParse = (e.getMessageAndLocation() =~ /^(.*) lineNumber: ([0-9]+); columnNumber: ([0-9]+); (.*).$/) |
|
| 155 |
if (msgParse.size() == 1) {
|
|
| 156 |
|
|
| 157 |
def lineNumber = msgParse[0][2] |
|
| 158 |
def colNumber = msgParse[0][3] |
|
| 159 |
def errMsg = msgParse[0][4] |
|
| 160 |
|
|
| 161 |
println "** $name [line $lineNumber, character $colNumber]: $errMsg." |
|
| 162 |
|
|
| 163 |
if (edit && (nEditors < maxEditors++)) {
|
|
| 164 |
def fileStore = EFS.getLocalFileSystem().getStore(xmlInputFile.toURI()) |
|
| 165 |
monitor.syncExec(new Runnable() {
|
|
| 166 |
public void run() {
|
|
| 167 |
def page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() |
|
| 168 |
editor = IDE.openEditorOnFileStore(page, fileStore) |
|
| 169 |
if (editor.getClass() == org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorPart) {
|
|
| 170 |
editor = editor.fTextEditor |
|
| 171 |
} |
|
| 172 |
def dprov = editor.getDocumentProvider() |
|
| 173 |
def doc = dprov.getDocument(editor.getEditorInput()) |
|
| 174 |
def nlines = doc.getNumberOfLines() |
|
| 175 |
def line = Integer.parseInt(lineNumber)-1 |
|
| 176 |
if (nlines < line) line = nlines-1 |
|
| 177 |
def ncols = doc.getLineLength(line) |
|
| 178 |
def col = Integer.parseInt(colNumber)-1 |
|
| 179 |
if (ncols <= col) col = ncols-1 |
|
| 180 |
def offset = doc.getLineOffset(line)+col |
|
| 181 |
def textv = editor.getAdapter(ITextOperationTarget.class) |
|
| 182 |
textv.getTextWidget().setSelection(offset) |
|
| 183 |
textv.revealRange(offset, 10) |
|
| 184 |
} // run |
|
| 185 |
} // Runnable |
|
| 186 |
) // syncExec |
|
| 187 |
} |
|
| 188 |
} else {
|
|
| 189 |
println e.getMessageAndLocation() |
|
| 190 |
} |
|
| 191 |
|
|
| 192 |
} |
|
| 193 |
} catch (Exception ee) {
|
|
| 194 |
//println "Warning: XSL transformation of '$name' failed with error=$e" |
|
| 195 |
//if (debug) " with: "+e.printStackTrace() |
|
| 196 |
XSLFile.delete() |
|
| 197 |
outputDirectory.deleteDir() |
|
| 198 |
return 0 |
|
| 199 |
} |
|
| 200 |
} |
|
| 201 |
|
|
| 202 |
XSLFile.delete() |
|
| 203 |
outputDirectory.deleteDir() |
|
| 204 |
|
|
| 205 |
return 1 |
|
| 206 |
|
|
Formats disponibles : Unified diff