Skip to content

Commit 17060e8

Browse files
authored
Merge pull request #4407 from evolvedbinary/feature/fn-matches
Use Saxon for fn:matches regular expression handling.
2 parents 41b500f + 816bdc4 commit 17060e8

File tree

2 files changed

+43
-15
lines changed

2 files changed

+43
-15
lines changed

exist-core/src/main/java/org/exist/xquery/functions/fn/FunMatches.java

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@
4141
import org.exist.xquery.value.StringValue;
4242
import org.exist.xquery.value.Type;
4343

44+
import java.util.ArrayList;
4445
import java.util.List;
4546
import java.util.regex.Matcher;
4647
import java.util.regex.Pattern;
4748
import java.util.regex.PatternSyntaxException;
49+
import net.sf.saxon.regex.RegularExpression;
4850

4951
import static org.exist.xquery.FunctionDSL.*;
5052
import static org.exist.xquery.functions.fn.FnModule.functionSignatures;
@@ -492,29 +494,39 @@ private Sequence evalFallback(final NodeSet nodes, final String pattern, final i
492494
private Sequence evalGeneric(final Sequence contextSequence, final Item contextItem, final Sequence input) throws XPathException {
493495
final String string = input.getStringValue();
494496

495-
final int flags;
497+
final String xmlRegexFlags;
496498
if (getSignature().getArgumentCount() == 3) {
497-
flags = parseFlags(this, getArgument(2).eval(contextSequence, contextItem).getStringValue());
499+
xmlRegexFlags = getArgument(2).eval(contextSequence, contextItem).getStringValue();
498500
} else {
499-
flags = 0;
501+
xmlRegexFlags = "";
500502
}
501503

502-
final String pattern;
504+
final String pattern = getArgument(1).eval(contextSequence, contextItem).getStringValue();
503505
if (isCalledAs("matches-regex")) {
504-
pattern = getArgument(1).eval(contextSequence, contextItem).getStringValue();
506+
final int flags = parseFlags(this, xmlRegexFlags);
507+
return BooleanValue.valueOf(match(string, pattern,flags));
505508
} else {
506-
final boolean literal = hasLiteral(flags);
507-
if (literal) {
508-
// no need to change anything
509-
pattern = getArgument(1).eval(contextSequence, contextItem).getStringValue();
510-
} else {
511-
final boolean ignoreWhitespace = hasIgnoreWhitespace(flags);
512-
final boolean caseBlind = hasCaseInsensitive(flags);
513-
pattern = translateRegexp(this, getArgument(1).eval(contextSequence, contextItem).getStringValue(), ignoreWhitespace, caseBlind);
514-
}
509+
return BooleanValue.valueOf(matchXmlRegex(string, pattern, xmlRegexFlags));
515510
}
511+
}
512+
513+
514+
private boolean matchXmlRegex(final String string, final String pattern, final String flags) throws XPathException {
515+
try {
516+
List<String> warnings = new ArrayList<>(1);
517+
RegularExpression regex = context.getBroker().getBrokerPool()
518+
.getSaxonConfiguration()
519+
.compileRegularExpression(pattern, flags, "XP30", warnings);
516520

517-
return BooleanValue.valueOf(match(string, pattern, flags));
521+
for (final String warning : warnings) {
522+
LOG.warn(warning);
523+
}
524+
525+
return regex.containsMatch(string);
526+
527+
} catch (final net.sf.saxon.trans.XPathException e) {
528+
throw new XPathException(this, ErrorCodes.FORX0001, "Invalid regular expression: " + e.getMessage(), new StringValue(pattern), e);
529+
}
518530
}
519531

520532
/**

exist-core/src/test/xquery/regex.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@
4949
<code>fn:matches('exist', '[a-z]{5}')</code>
5050
<expected>true</expected>
5151
</test>
52+
<test output="text">
53+
<task>fn:matches-using-hyphen-postfix</task>
54+
<code>fn:matches('aww he--', '[l-]')</code>
55+
<expected>true</expected>
56+
</test>
57+
<test output="text">
58+
<task>fn:matches-using-hyphen-prefix</task>
59+
<code>fn:matches('aww he--', '[-l]')</code>
60+
<expected>true</expected>
61+
</test>
5262
<test output="text">
5363
<task>fn:matches-xflag-1</task>
5464
<code>fn:matches('helloworld', 'hello world', 'x')</code>
@@ -80,6 +90,12 @@
8090
<expected>true</expected>
8191
</test>
8292

93+
<test output="text">
94+
<task>fn:matches-jflags-1</task>
95+
<code>fn:matches("(", "\p{javaMirrored}", ";j")</code>
96+
<expected>true</expected>
97+
</test>
98+
8399
<test output="text">
84100
<task>fn:replace1</task>
85101
<code>fn:replace('eximtdb', 'm', 's')</code>

0 commit comments

Comments
 (0)