From 58d0a9c64b5605a76d58609499f211d264684baf Mon Sep 17 00:00:00 2001 From: marmoure Date: Mon, 7 Sep 2026 10:45:49 +0200 Subject: [PATCH 1/9] [feature] Create the function stub and add to the fn namespace --- .../xquery/functions/fn/FnInvisibleXml.java | 57 +++++++++++++++++++ .../exist/xquery/functions/fn/FnModule.java | 3 +- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java diff --git a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java new file mode 100644 index 0000000000..46c0f2bb1b --- /dev/null +++ b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java @@ -0,0 +1,57 @@ +/* + * Elemental + * Copyright (C) 2024, Evolved Binary Ltd + * + * admin@evolvedbinary.com + * https://www.evolvedbinary.com | https://www.elemental.xyz + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.exist.xquery.functions.fn; + +import org.exist.dom.QName; +import org.exist.xquery.BasicFunction; +import org.exist.xquery.Cardinality; +import org.exist.xquery.FunctionSignature; +import org.exist.xquery.XPathException; +import org.exist.xquery.XQueryContext; +import org.exist.xquery.value.FunctionReturnSequenceType; +import org.exist.xquery.value.Sequence; +import org.exist.xquery.value.StringValue; +import org.exist.xquery.value.Type; + +public class FnInvisibleXml extends BasicFunction { + + private static final String FS_INVISIBLE_XML_NAME = "invisible-xml"; + + /** + * Note for the arguments one of them takses 2 types and I need to create a super type use transform.java as example + */ + + public final static FunctionSignature FNS_INVISIBLE_XML = new FunctionSignature( + new QName(FS_INVISIBLE_XML_NAME, FnModule.NAMESPACE_URI), + "Evaluates invisible XML.", + null, + new FunctionReturnSequenceType(Type.STRING, Cardinality.EXACTLY_ONE, "The evaluated string.") + ); + + public FnInvisibleXml(final XQueryContext context, final FunctionSignature signature) { + super(context, signature); + } + + @Override + public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException { + return new StringValue("TODO TODO TODO, maybe next"); + } +} \ No newline at end of file diff --git a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnModule.java b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnModule.java index e801e9ce75..797309895f 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnModule.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnModule.java @@ -299,7 +299,8 @@ public class FnModule extends AbstractInternalModule { new FunctionDef(FnRandomNumberGenerator.FS_RANDOM_NUMBER_GENERATOR[0], FnRandomNumberGenerator.class), new FunctionDef(FnRandomNumberGenerator.FS_RANDOM_NUMBER_GENERATOR[1], FnRandomNumberGenerator.class), new FunctionDef(FunContainsToken.FS_CONTAINS_TOKEN[0], FunContainsToken.class), - new FunctionDef(FunContainsToken.FS_CONTAINS_TOKEN[1], FunContainsToken.class) + new FunctionDef(FunContainsToken.FS_CONTAINS_TOKEN[1], FunContainsToken.class), + new FunctionDef(FnInvisibleXml.FNS_INVISIBLE_XML, FnInvisibleXml.class) }; static { From caec4f3e51ff359b6f6e58cf67be68e325854e6d Mon Sep 17 00:00:00 2001 From: marmoure Date: Tue, 8 Sep 2026 15:25:14 +0200 Subject: [PATCH 2/9] [feature] Add error codes. --- .../java/org/exist/xquery/ErrorCodes.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/exist-core/src/main/java/org/exist/xquery/ErrorCodes.java b/exist-core/src/main/java/org/exist/xquery/ErrorCodes.java index 6183cc35b2..067cbd0ec1 100644 --- a/exist-core/src/main/java/org/exist/xquery/ErrorCodes.java +++ b/exist-core/src/main/java/org/exist/xquery/ErrorCodes.java @@ -328,6 +328,9 @@ public enum W3CErrorCode implements IErrorCode { FOXT0003 ("XSLT transformation failed"), FOXT0004 ("XSLT transformation has been disabled"), FOXT0006 ("XSLT output contains non-accepted characters"), + FOIX0001 ("Invalid Invisible XML grammar."), + FOIX0002 ("Input provided could not be parsed successfully."), + FOIX0003 ("No Invisible XML processor is available."), XTSE0165 ("It is a static error if the processor is not able to retrieve the resource identified by the URI reference [ in the href attribute of xsl:include or xsl:import] , or if the resource that is retrieved does not contain a stylesheet module conforming to this specification."); private final ErrorCode errorCode; @@ -1537,6 +1540,24 @@ public DynamicErrorCode(final QName qname, @Nullable final String description) { @Deprecated public static final ErrorCode FOXT0006 = W3CErrorCode.FOXT0006.errorCode; + /** + * @deprecated Use {@link W3CErrorCode#FOIX0001}. + */ + @Deprecated + public static final ErrorCode FOIX0001 = W3CErrorCode.FOIX0001.errorCode; + + /** + * @deprecated Use {@link W3CErrorCode#FOIX0002}. + */ + @Deprecated + public static final ErrorCode FOIX0002 = W3CErrorCode.FOIX0002.errorCode; + + /** + * @deprecated Use {@link W3CErrorCode#FOIX0003}. + */ + @Deprecated + public static final ErrorCode FOIX0003 = W3CErrorCode.FOIX0003.errorCode; + /** * @deprecated Use {@link W3CErrorCode#XTSE0165}. */ From 939573f125e741a15d45e18f462f05d819784409 Mon Sep 17 00:00:00 2001 From: marmoure Date: Wed, 9 Sep 2026 18:43:51 +0200 Subject: [PATCH 3/9] [bugfix] Typo --- .../src/main/java/org/exist/xquery/functions/fn/FnModule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnModule.java b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnModule.java index 797309895f..16367be1c4 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnModule.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnModule.java @@ -300,7 +300,7 @@ public class FnModule extends AbstractInternalModule { new FunctionDef(FnRandomNumberGenerator.FS_RANDOM_NUMBER_GENERATOR[1], FnRandomNumberGenerator.class), new FunctionDef(FunContainsToken.FS_CONTAINS_TOKEN[0], FunContainsToken.class), new FunctionDef(FunContainsToken.FS_CONTAINS_TOKEN[1], FunContainsToken.class), - new FunctionDef(FnInvisibleXml.FNS_INVISIBLE_XML, FnInvisibleXml.class) + new FunctionDef(FnInvisibleXml.FS_INVISIBLE_XML, FnInvisibleXml.class) }; static { From e63d5936186f1a3979cd805da2c32c8e94482612 Mon Sep 17 00:00:00 2001 From: marmoure Date: Wed, 9 Sep 2026 18:44:15 +0200 Subject: [PATCH 4/9] [feature] Use markup blitz for the IXML grammar parsing --- exist-core/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/exist-core/pom.xml b/exist-core/pom.xml index 677e244476..57fcc2ff3f 100644 --- a/exist-core/pom.xml +++ b/exist-core/pom.xml @@ -584,6 +584,12 @@ + + de.bottlecaps + markup-blitz + 1.12 + + xyz.elemental.fork.org.exist-db From dc93784cabcdfb371e67c7a281cc6b187a5c078b Mon Sep 17 00:00:00 2001 From: marmoure Date: Wed, 9 Sep 2026 18:45:24 +0200 Subject: [PATCH 5/9] [feature] First attempt at creating a User defined function and returning it. --- .../xquery/functions/fn/FnInvisibleXml.java | 52 ++++++++++++------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java index 46c0f2bb1b..5cda61ff49 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java @@ -20,31 +20,22 @@ */ package org.exist.xquery.functions.fn; +import static org.exist.xquery.functions.fn.FnModule.functionSignature; +import static org.exist.xquery.FunctionDSL.returns; + import org.exist.dom.QName; -import org.exist.xquery.BasicFunction; -import org.exist.xquery.Cardinality; -import org.exist.xquery.FunctionSignature; -import org.exist.xquery.XPathException; -import org.exist.xquery.XQueryContext; -import org.exist.xquery.value.FunctionReturnSequenceType; -import org.exist.xquery.value.Sequence; -import org.exist.xquery.value.StringValue; -import org.exist.xquery.value.Type; +import org.exist.xquery.*; +import org.exist.xquery.value.*; public class FnInvisibleXml extends BasicFunction { private static final String FS_INVISIBLE_XML_NAME = "invisible-xml"; - /** - * Note for the arguments one of them takses 2 types and I need to create a super type use transform.java as example - */ - - public final static FunctionSignature FNS_INVISIBLE_XML = new FunctionSignature( + public final static FunctionSignature FS_INVISIBLE_XML = new FunctionSignature( new QName(FS_INVISIBLE_XML_NAME, FnModule.NAMESPACE_URI), "Evaluates invisible XML.", null, - new FunctionReturnSequenceType(Type.STRING, Cardinality.EXACTLY_ONE, "The evaluated string.") - ); + new FunctionReturnSequenceType(Type.FUNCTION, Cardinality.EXACTLY_ONE, "The parser function.")); public FnInvisibleXml(final XQueryContext context, final FunctionSignature signature) { super(context, signature); @@ -52,6 +43,31 @@ public FnInvisibleXml(final XQueryContext context, final FunctionSignature signa @Override public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException { - return new StringValue("TODO TODO TODO, maybe next"); + final IxmlParserFunction fn = new IxmlParserFunction(context); // QUESTIONS : where context?? + final FunctionCall call = new FunctionCall(context, fn); + return new FunctionReference(call); + } + + private static class IxmlParserFunction extends UserDefinedFunction { + + IxmlParserFunction(final XQueryContext context) { + super(context, functionSignature( + "invisible-xml", + "Gets the next random number generator.", + returns(Type.STRING, "just a random string for now"))); + } + + @Override + public Sequence eval(final Sequence contextSequence, final Item contextItem) throws XPathException { + return new StringValue("inner function return value"); + } + + @Override + public void accept(final ExpressionVisitor visitor) { + if (visited) { + return; + } + visited = true; + } } -} \ No newline at end of file +} From d516e21ea7986b1b41ceb682fc4ccdd549af0b26 Mon Sep 17 00:00:00 2001 From: marmoure Date: Wed, 9 Sep 2026 18:55:31 +0200 Subject: [PATCH 6/9] [feature] The inner function can take input now, and it retuns it as it is. --- .../java/org/exist/xquery/functions/fn/FnInvisibleXml.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java index 5cda61ff49..7e4a215f20 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java @@ -21,6 +21,7 @@ package org.exist.xquery.functions.fn; import static org.exist.xquery.functions.fn.FnModule.functionSignature; +import static org.exist.xquery.FunctionDSL.param; import static org.exist.xquery.FunctionDSL.returns; import org.exist.dom.QName; @@ -54,12 +55,14 @@ private static class IxmlParserFunction extends UserDefinedFunction { super(context, functionSignature( "invisible-xml", "Gets the next random number generator.", - returns(Type.STRING, "just a random string for now"))); + returns(Type.STRING, "just a random string for now"), + param("Parser inpuit", Type.STRING, "param description"))); } @Override public Sequence eval(final Sequence contextSequence, final Item contextItem) throws XPathException { - return new StringValue("inner function return value"); + String parserInput = getCurrentArguments()[0].itemAt(0).getStringValue(); + return new StringValue(parserInput); } @Override From 1584f3cf57ed12cd95921bf42f421db15bf58bde Mon Sep 17 00:00:00 2001 From: marmoure Date: Wed, 9 Sep 2026 19:13:54 +0200 Subject: [PATCH 7/9] [feature] Use the default IXML parser to parse input and return it as string --- .../org/exist/xquery/functions/fn/FnInvisibleXml.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java index 7e4a215f20..791695fda7 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java @@ -28,6 +28,8 @@ import org.exist.xquery.*; import org.exist.xquery.value.*; +import de.bottlecaps.markup.Blitz; + public class FnInvisibleXml extends BasicFunction { private static final String FS_INVISIBLE_XML_NAME = "invisible-xml"; @@ -62,7 +64,12 @@ private static class IxmlParserFunction extends UserDefinedFunction { @Override public Sequence eval(final Sequence contextSequence, final Item contextItem) throws XPathException { String parserInput = getCurrentArguments()[0].itemAt(0).getStringValue(); - return new StringValue(parserInput); + // generate the default ixml grammar + String ixmlGrammar = Blitz.ixmlGrammar(); + // parse the input using the ixml grammar + String generatedXML = Blitz.generate(ixmlGrammar).parse(parserInput); + + return new StringValue(generatedXML); } @Override From fe29b7ca7e3b375544392167a1e7bd64535cf71b Mon Sep 17 00:00:00 2001 From: marmoure Date: Thu, 10 Sep 2026 12:42:58 +0200 Subject: [PATCH 8/9] [feature] Build a document from the Blitz grammar response. --- .../xquery/functions/fn/FnInvisibleXml.java | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java index 791695fda7..5323b2f9cd 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java @@ -18,18 +18,31 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + package org.exist.xquery.functions.fn; import static org.exist.xquery.functions.fn.FnModule.functionSignature; import static org.exist.xquery.FunctionDSL.param; import static org.exist.xquery.FunctionDSL.returns; +import org.exist.Namespaces; import org.exist.dom.QName; +import org.exist.dom.memtree.DocumentImpl; +import org.exist.dom.memtree.MemTreeBuilder; +import org.exist.dom.memtree.NodeImpl; +import org.exist.dom.memtree.SAXAdapter; +import org.exist.util.XMLReaderPool; +import org.exist.validation.ValidationReport; import org.exist.xquery.*; +import org.exist.xquery.functions.validation.Shared; import org.exist.xquery.value.*; +import org.xml.sax.*; import de.bottlecaps.markup.Blitz; +import java.io.IOException; +import java.io.StringReader; + public class FnInvisibleXml extends BasicFunction { private static final String FS_INVISIBLE_XML_NAME = "invisible-xml"; @@ -57,7 +70,7 @@ private static class IxmlParserFunction extends UserDefinedFunction { super(context, functionSignature( "invisible-xml", "Gets the next random number generator.", - returns(Type.STRING, "just a random string for now"), + returns(Type.DOCUMENT, "just a random string for now"), param("Parser inpuit", Type.STRING, "param description"))); } @@ -69,7 +82,25 @@ public Sequence eval(final Sequence contextSequence, final Item contextItem) thr // parse the input using the ixml grammar String generatedXML = Blitz.generate(ixmlGrammar).parse(parserInput); - return new StringValue(generatedXML); + return parse(generatedXML, null); + } + + private Sequence parse(final String xmlContent, final Sequence[] args) throws XPathException { + DocumentImpl document = null; + final SAXAdapter adapter = new SAXAdapter(context); + try { + XMLReaderPool pool = context.getBroker().getBrokerPool().getParserPool(); + XMLReader reader = pool.borrowXMLReader(); + reader.setContentHandler(adapter); + reader.setProperty(Namespaces.SAX_LEXICAL_HANDLER, adapter); + reader.parse(new InputSource(new StringReader(xmlContent))); + document = adapter.getDocument(); + } catch (Exception e) { + + } finally { + return document; + } + } @Override From e841762c2efbe284e36de1e175660f266baae299 Mon Sep 17 00:00:00 2001 From: Adam Retter Date: Thu, 10 Sep 2026 13:36:46 +0200 Subject: [PATCH 9/9] Review and discussion --- .../xquery/functions/fn/FnInvisibleXml.java | 131 ++++++++++++------ 1 file changed, 90 insertions(+), 41 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java index 5323b2f9cd..cceb2c91de 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/fn/FnInvisibleXml.java @@ -21,25 +21,26 @@ package org.exist.xquery.functions.fn; +import static com.evolvedbinary.j8fu.Either.Left; +import static com.evolvedbinary.j8fu.Either.Right; +import static org.exist.xquery.FunctionDSL.optParam; import static org.exist.xquery.functions.fn.FnModule.functionSignature; import static org.exist.xquery.FunctionDSL.param; import static org.exist.xquery.FunctionDSL.returns; +import com.evolvedbinary.j8fu.Either; import org.exist.Namespaces; -import org.exist.dom.QName; -import org.exist.dom.memtree.DocumentImpl; -import org.exist.dom.memtree.MemTreeBuilder; -import org.exist.dom.memtree.NodeImpl; import org.exist.dom.memtree.SAXAdapter; import org.exist.util.XMLReaderPool; -import org.exist.validation.ValidationReport; import org.exist.xquery.*; -import org.exist.xquery.functions.validation.Shared; +import org.exist.xquery.functions.map.MapType; import org.exist.xquery.value.*; +import org.w3c.dom.Element; import org.xml.sax.*; import de.bottlecaps.markup.Blitz; +import javax.annotation.Nullable; import java.io.IOException; import java.io.StringReader; @@ -47,11 +48,13 @@ public class FnInvisibleXml extends BasicFunction { private static final String FS_INVISIBLE_XML_NAME = "invisible-xml"; - public final static FunctionSignature FS_INVISIBLE_XML = new FunctionSignature( - new QName(FS_INVISIBLE_XML_NAME, FnModule.NAMESPACE_URI), + final static FunctionSignature FS_INVISIBLE_XML = functionSignature( + FS_INVISIBLE_XML_NAME, "Evaluates invisible XML.", - null, - new FunctionReturnSequenceType(Type.FUNCTION, Cardinality.EXACTLY_ONE, "The parser function.")); + returns(Type.FUNCTION, "The iXML parsing function"), + optParam("grammar", Type.ITEM, "The iXML grammar"), + optParam("options", Type.MAP_ITEM, "Options for the iXML parser") + ); public FnInvisibleXml(final XQueryContext context, final FunctionSignature signature) { super(context, signature); @@ -59,56 +62,102 @@ public FnInvisibleXml(final XQueryContext context, final FunctionSignature signa @Override public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException { - final IxmlParserFunction fn = new IxmlParserFunction(context); // QUESTIONS : where context?? - final FunctionCall call = new FunctionCall(context, fn); - return new FunctionReference(call); + final Sequence optionsArg = args[1]; + @Nullable final MapType options; + if (optionsArg.isEmpty()) { + options = null; + } else { + options = optionsArg.itemAt(0).toJavaObject(MapType.class); + } + + final IxmlParserFunction fn; + final Sequence grammarArg = args[0]; + if (grammarArg.isEmpty()) { + // no grammar provided + fn = new IxmlParserFunction(context, (StringValue) null, options); + + } else if (grammarArg.getItemType() == Type.STRING) { + // grammar is a string + final StringValue grammarString = grammarArg.itemAt(0).toJavaObject(StringValue.class); + fn = new IxmlParserFunction(context, grammarString, options); + + } else { + // grammar is an element + final Element grammarElement = grammarArg.itemAt(0).toJavaObject(Element.class); + fn = new IxmlParserFunction(context, grammarElement, options); + } + + final InlineFunction functionResult = new InlineFunction(context, fn); + return functionResult.eval(contextSequence, null); } private static class IxmlParserFunction extends UserDefinedFunction { - IxmlParserFunction(final XQueryContext context) { - super(context, functionSignature( - "invisible-xml", - "Gets the next random number generator.", - returns(Type.DOCUMENT, "just a random string for now"), - param("Parser inpuit", Type.STRING, "param description"))); + private static final String FS_PARSE_INVISIBLE_XML_NAME = "parse-invisible-xml"; + private static final FunctionSignature FS_PARSE_INVISIBLE_XML = functionSignature( + FS_PARSE_INVISIBLE_XML_NAME, + "Gets the next random number generator.", + returns(Type.DOCUMENT, "just a random string for now"), + param("Parser inpuit", Type.STRING, "param description") + ); + + @Nullable final Either grammar; + @Nullable final MapType options; + + IxmlParserFunction(final XQueryContext context, @Nullable final StringValue grammar, @Nullable final MapType options) { + super(context, FS_PARSE_INVISIBLE_XML); + this.grammar = Left(grammar); + this.options = options; + } + + IxmlParserFunction(final XQueryContext context, @Nullable final Element grammar, @Nullable final MapType options) { + super(context, FS_PARSE_INVISIBLE_XML); + this.grammar = Right(grammar); + this.options = options; } @Override public Sequence eval(final Sequence contextSequence, final Item contextItem) throws XPathException { - String parserInput = getCurrentArguments()[0].itemAt(0).getStringValue(); + + // get the input + final Sequence inputArg = getArguments(contextSequence, contextItem)[0]; + final String input = inputArg.itemAt(0).getStringValue(); + // generate the default ixml grammar - String ixmlGrammar = Blitz.ixmlGrammar(); + final String ixmlGrammar; + if (grammar == null) { + ixmlGrammar = Blitz.ixmlGrammar(); + } else if (grammar.isLeft()) { + ixmlGrammar = grammar.left().get().getStringValue(); + } else { + // TODO(YB) use XQuerySerializer class to serialize Element to String + ixmlGrammar = ... + } + + // TODO(YB) set any options + // parse the input using the ixml grammar - String generatedXML = Blitz.generate(ixmlGrammar).parse(parserInput); + final String generatedXML = Blitz.generate(ixmlGrammar).parse(input); - return parse(generatedXML, null); + return parse(generatedXML); } - private Sequence parse(final String xmlContent, final Sequence[] args) throws XPathException { - DocumentImpl document = null; + private Sequence parse(final String xmlContent) throws XPathException { + final XMLReaderPool pool = context.getBroker().getBrokerPool().getParserPool(); final SAXAdapter adapter = new SAXAdapter(context); - try { - XMLReaderPool pool = context.getBroker().getBrokerPool().getParserPool(); - XMLReader reader = pool.borrowXMLReader(); + final XMLReader reader = pool.borrowXMLReader(); + try (final StringReader stringReader = new StringReader(xmlContent)) { reader.setContentHandler(adapter); reader.setProperty(Namespaces.SAX_LEXICAL_HANDLER, adapter); - reader.parse(new InputSource(new StringReader(xmlContent))); - document = adapter.getDocument(); - } catch (Exception e) { - + reader.parse(new InputSource(stringReader)); + return adapter.getDocument(); + } catch (final SAXException | IOException e) { + // TODO(YB) add error code + throw new XPathException(this, e.getMessage(), e); } finally { - return document; + pool.returnXMLReader(reader); } } - - @Override - public void accept(final ExpressionVisitor visitor) { - if (visited) { - return; - } - visited = true; - } } }