Why is caret an illegal character in this regular expression? - java

The environment is Java 8, Saxon 9.8 processor, XSL Stylesheet Version 3, running from Eclipse.
Given the following xslt command in the stylesheet:
<xsl:variable name="output"
select="fn:replace($inputstring,
'^.*exec\s+sp_prepexec.+?N'([^#](?:[^'']|'''')+)''.*$', '$1', 'ism;j')" />
Produces the stacktrace:
net.sf.saxon.trans.XPathException: Invalid character '^' in expression
at net.sf.saxon.expr.parser.XPathParser.grumble(XPathParser.java:281)
at net.sf.saxon.expr.parser.XPathParser.grumble(XPathParser.java:238)
at net.sf.saxon.expr.parser.XPathParser.grumble(XPathParser.java:225)
at net.sf.saxon.expr.parser.XPathParser.nextToken(XPathParser.java:196)
at net.sf.saxon.expr.parser.XPathParser.parseDynamicFunctionCall(XPathParser.java:2358)
at net.sf.saxon.expr.parser.XPathParser.parseStepExpression(XPathParser.java:1974)
...
at org.eclipse.wst.xsl.jaxp.debug.invoker.internal.Main.main(Main.java:72)
I did not find any clue why a caret won't be allowed in that expression - can you support me debugging this?
I was wondering if escaping is a problem, in the code line above I doubled single apostrophes in the expression, also tried it with &apos;, but it is always the same error message.
Given from the flags I assume that Saxon would use the Java regex parser for this, but the returned stack trace does not show that.
This is an example of the input string I want to process:
declare #p1 int
set #p1=328
exec sp_prepexec #p1 output,N'#P1 int,#P2 char(1),#P3 char(1)',N'SELECT "Tbl1009"."RUN_NO" "Col1111","Tbl1009"."DEP_ID" "Col1114" FROM "run" "Tbl1009" WHERE #P1="Tbl1009"."RUN_ID" AND ("Tbl1009"."Profile_ID"=(1) AND #P2=''N'' OR "Tbl1009"."Profile_ID"=(5) AND #P3=''Y'') AND ("Tbl1009"."Profile_ID"=(1) OR "Tbl1009"."Profile_ID"=(5))',150,'N','N'
select #p1
and the required output:
SELECT "Tbl1009"."RUN_NO" "Col1111","Tbl1009"."DEP_ID" "Col1114" FROM "run" "Tbl1009" WHERE #P1="Tbl1009"."RUN_ID" AND ("Tbl1009"."Profile_ID"=(1) AND #P2=''N'' OR "Tbl1009"."Profile_ID"=(5) AND #P3=''Y'') AND ("Tbl1009"."Profile_ID"=(1) OR "Tbl1009"."Profile_ID"=(5))

#WillBarnwell has the correct diagnosis but the wrong solution. The problem with the ' isn't that it is special in regular expressions, the problem is that it is special in XPath, so you need to use XPath-level escaping, and the way to do that is to write it as two apostrophes. This can get pretty bewildering so the best thing is often to move the regex to a variable defined with content:
<xsl:variable name="regex" as="xs:string"
>^.*exec\s+sp_prepexec.+?N'([^#](?:[^']|'')+)'.*$</xsl:variable>
<xsl:variable name="output"
select="fn:replace($inputstring, $regex, '$1', 'ism;j')" />
(Check that carefully because I'm not sure I have fully understood your intent).

syntax error, your regex is ending at the first unescaped single quote and is being interpreted as ^.*exec\s+sp_prepexec.+?N this is then followed by ([^ with ^ being the first illegal character. Notice that the error is originating from the XML parser, not the regex engine.
Escaping your single quotes with \' is not the way to solve this, as #Michael-Kay shows it is define your regex in a variable.

Related

Regex Expression working in Notepad++ but not Java

Okay, so i'm working on a problem I'd rather solve with regex, I test most of my regex expressions in Notepad++, This has worked fine after a few tweaks such as double escaping some things for java, However this regex expression throws an exception when run in java, however it runs in Notepad++ just fine, the idea if this code is to be able to mention a different player in the game with a highlighted name.
tldr; I'm trying to replace the first occurrence of a specific name in a message
I've tried looking around for a while but i haven't found a solution, so i thought i might as well ask here.
p.getName() simply returns a string (the players name)
String newmessage = message.replaceFirst("(?i)" + Pattern.quote(p.getName()) + "((?(?=\\s)|('|,|!))|$)", color + p.getName() + Color.toString(Color.getLastColorOf(message)));
However executing the code throws this exception
...at java.lang.Thread.run(Unknown Source) [?:1.8.0_202]
Caused by: java.util.regex.PatternSyntaxException: Unknown inline modifier near index 15
(?i)\QTauCubed\E((?(?=\s)|('|,))|$)
^
at java.util.regex.Pattern.error(Unknown Source) ~[?:1.8.0_202]...
And I'm not sure what it wants me to do, I don't see how this is not valid regex
This is the regex for Notepad++
(?i)Name((?(?=\s)|('|,|!))|$)
The above will match
Name's r
Name
Name test
Name,
Name!
But will not match
Nametest
That is what I intended it to do.
I vote for just using the pattern \bName\b along with String#replaceFirst:
String input = "Rename here is a Name and here is the same Name again.";
input = input.replaceFirst("\\bName\\b", "blah");
System.out.println(input);
This prints:
Rename here is a blah and here is the same Name again.

Java CSVeed library, option for quote inside unquoted field?

I'm benching several Java libraries to parse csv files. I can't find a solution for the CSVeed library with this line :
af,dekh"iykh'ya,Dekh"iykh'ya,13,,34.60345,69.2405
I have this error :
org.csveed.report.CsvException: Illegal state transition:
Parsing symbol QUOTE_SYMBOL [34] in state INSIDE_FIELD
19970: af,dekh
I understand very well what happen unfortunately I tried different blend of options without succeed. Is there a way?
In fact the perfect line of 7 cols should be :
af,dekh\"iykh\'ya,Dekh\"iykh\'ya,13,,34.60345,69.2405
af,dekh"iykh'ya,Dekh"iykh'ya,13,,34.60345,69.2405
To parse this in the following fields you'll have to turn quoting off in your parser:
af
dekh"iykh'ya
Dekh"iykh'ya
13
<null>
34.60345
69.2405
If quoting can not be turned off, you could use setQuote(char symbol) and provide an unused char as parameter.

How to check, that array has size > 1 in Apache FreeMarker?

I'm trying to implement template with object, that can be plural.
For example: "There is/are n dog(s)."
When I tried There <#if dogNames?size>1>is<#else>are</#if> dogNames?size dog<#if dogNames?size>1>s</#if>, I received exception
freemarker.core.NonBooleanException: For "#if" condition: Expected a boolean, but this has evaluated to a number (wrapper: f.t.SimpleNumber):
==> dogNames?size
i.e. there is a problem with angle bracket used for comparison.
In this blog it is said that double quotes is enough to escape the bracket, but I'm not managed to do that in Java. When I declared it like this
String template = "There <#if dogNames?size\">\"1>is<#else>are</#if> dogNames?size dog<#if dogNames?size>1>s</#if>";
and called freemarker api, I received exception
freemarker.core.ParseException: Syntax error in template ...:
Encountered "\">\"", but was expecting one of:
"."
".."
<DOT_DOT_LESS>
"..*"
"?"
"??"
"!"
"["
"("
">"
<TERMINATING_EXCLAM>
I'm using freemarker 2.3.28, java 8
You can write <#if dogNames?size gt 1>. (See https://freemarker.apache.org/docs/dgui_template_exp.html#dgui_template_exp_comparison)

OSB fn:bea Function using XQuery Engine in Java

After some research I haven't found a solution, but quite alot of people with this problem:
I am trying to do a XQuery Transformation in a Java Application using
net.sf.saxon.s9api
However I get this error when trying to compile XQueryExecutable exec = compiler.compile(...)); my XQuery:
Error on line 13 column 3 of AivPumaRequest.xquery:
XPST0081 XQuery static error near #... fn-bea:inlinedXML(fn:concat#:
Prefix fn-bea has not been declared
Error on line 44 column 102 of AivPumaRequest.xquery:
XPST0081 XQuery static error near #... div xdt:dayTimeDuration('P1D'#:
Prefix xdt has not been declared
Error on line 199 column 3 of AivPumaRequest.xquery:
XPST0081 XQuery static error near #... fn-bea:inlinedXML(fn:concat#:
Prefix fn-bea has not been declared
Error on line 282 column 4 of AivPumaRequest.xquery:
XPST0081 XQuery static error near #... {fn-bea:inlinedXML(fn:concat#:
Prefix fn-bea has not been declared
net.sf.saxon.s9api.SaxonApiException: Prefix fn-bea has not been declared
Is there a way to static include this prefix or what am I missing so my XQuery Engine (SAXON) finds the Prefix?
The simple answer to your question is that you can declare namespace prefixes either within the query prolog using
declare namespace fn-bea = "http://some-appropriate-uri";
or in the Saxon API using
XQueryCompiler.declareNamespace("fn-bea", "http://some-appropriate-uri")
But this won't get you any further unless (a) you know what URI to bind the prefixes to, and (b) you make the functions with these names available to the query processor.
The reference to xdt:dayTimeDuration suggests to me that this query was written when XQuery was still a working draft. If you look at the 2005 working draft, for example
https://www.w3.org/TR/2005/CR-xquery-20051103/
you'll see in section 2 that it uses a built-in prefix
xdt = http://www.w3.org/2005/xpath-datatypes
By the time XQuery 1.0 became a recommendation, the dayTimeDuration data type had been moved into the standard XML Schema (xs) namespace, so you can probably simply replace "xdt" by "xs" - though you should be aware that the semantics of the language probably changed in minor details as well.
As for fn-bea:inlinedXML, the choice of prefix suggests to me that this was probably a built-in vendor extension in the BEA query processor, which was taken over by Oracle. The spec here:
https://docs.oracle.com/cd/E13162_01/odsi/docs10gr3/xquery/extensions.html
says:
fn-bea:inlinedXML Parses textual XML and returns an instance of the
XQuery 1.0 Data Model.
Which suggests that the function does something very similar to the XQuery 3.0 function fn:parse-xml(), and I suggest you try making that replacement in your query.

Velocity parser crashes when parsing java code template

When trying to use a java source code as template for Velocity, it crashes at this line of the template:
/* #see panama.form.Validator#validate(java.lang.Object) */
with this Exception:
Exception in thread "main" org.apache.velocity.exception.ParseErrorException: Lexical error, Encountered: "l" (108), after : "." at *unset*[line 23, column 53]
at org.apache.velocity.runtime.RuntimeInstance.evaluate(RuntimeInstance.java:1301)
at org.apache.velocity.runtime.RuntimeInstance.evaluate(RuntimeInstance.java:1265)
at org.apache.velocity.app.VelocityEngine.evaluate(VelocityEngine.java:199)
Apparently it takes the #validate for a macro and crashes when it tries to parse the arguments for the macro. Is there anything one could do about this?
I'm using Velocity 1.7.
Edit
I know I could escape the # characters in the template files, but there are quite a number of them which also might change now and then, so I would prefer a way that would not require manual changes on the files.
First option
Try this solution from here: Escaping VTL Directives
VTL directives can be escaped with the backslash character ("\") in a manner similar to valid VTL references.
## #include( "a.txt" ) renders as <contents of a.txt>
#include( "a.txt" )
## \#include( "a.txt" ) renders as #include( "a.txt" )
\#include( "a.txt" )
## \\#include ( "a.txt" ) renders as \<contents of a.txt>
\\#include ( "a.txt" )
Second option
You have this tool [EscapeTool][2].
Tool for working with escaping in Velocity templates.
It provides methods to escape outputs for Java, JavaScript, HTML, XML and SQL. Also provides methods to render VTL characters that otherwise needs escaping.
Third option:
You may also try this workaround, I didn't use it but it should work:
You can at the beginning read your template as a String and then pre-parse it. For example replace all # with \#, or add to the beginning of file
#set( $H = '#' )
$H$H
see this answer: How to escape a # in velocity And then from that pre-parsed String create Template by using this answer: How to use String as Velocity Template?

Categories

Resources