Когда я пытаюсь запустить следующее выражение xpath в Java, используя VTD-XML, я получаю непредвиденную ошибку.
Код:
..
AutoPilot ap = new AutoPilot(vn);
ap.selectXPath("/a//b[text() = 'apple''banana']");
Ошибка:
Syntax error after or around the end of ==> /a//b[text() = 'apple'
Caused by: com.ximpleware.XPathParseException: XPath Syntax error: #29
at com.ximpleware.xpath.parser.unrecovered_syntax_error(parser.java:492)
at java_cup.runtime.lr_parser.parse(lr_parser.java:601)
at com.ximpleware.AutoPilot.selectXPath(AutoPilot.java:809)
Это не ошибка? У меня создалось впечатление, что избежать одиночных кавычек в XPath 2.0 было приемлемым? Когда я пытаюсь запустить xpath-запрос в XML-шпионах с тем же документом, он работает нормально.
К сожалению, похоже, что экранирование не является вариантом, мне пришлось написать пользовательскую функцию, основанную на следующем:
XQuery ищет текст с "одной" цитатой
Он был написан в javascript, поэтому я преобразовал его в Java:
private static String cleanStringForXPath(String dirtyString)
{
Pattern pattern = Pattern.compile("([^'\"]+|['\"])");
Matcher matcher = pattern.matcher(dirtyString);
int count = 0;
StringBuilder sb = new StringBuilder();
while(matcher.find()) {
String part = matcher.group(1);
if(part.equals("'")) {
sb.append("\"'\"");
} else if(part.equals("\"")) {
sb.append("'\"'");
} else {
sb.append("'" + part + "'");
}
sb.append(",");
count++;
}
String result = sb.length() > 0 ? sb.substring(0, sb.length() - 1): "";
return (count > 1) ? "concat(" + result + ")" : result;
}
Я протестировал эту функцию и, похоже, решил проблему.
Поскольку XPath также может поддерживать строки ".."
которые могут содержать unescaped -s, вы можете просто использовать:
ap.selectXPath("/a//b[text() = \"apple'banana\"]");
Escaping - это вопрос, который полностью оставлен на языке хоста, который использует XPath для запроса данных. Правила экранирования этого языка более высокого уровня обычно также применяются к выражениям XPath, используемым в нем.
Я цитирую из Michael Kay XPath 2.0 Programmer Reference:
Аналогично, когда выражения XPath записываются в символьных строках на языке хоста, таком как Java, вам нужно будет использовать соглашения об экранировании этого языка: например, [...] кавычка как
\"
.
Другими словами, ''
исключает одну цитату в XSLT 2.0. В Java одиночная кавычка должна быть экранирована как \'
я думаю".
ap.selectXPath("/a//b[text() = 'apple\'banana']");
/a//b[. = $targetValue]
). Но VTD-XML позволяет вам задавать переменную только путем оценки другого выражения XPath, в отличие от всех других реализаций XPath, о которых я знаю, которые позволяют вам напрямую вводить строку или число Java в качестве значения переменной.