XPath normalize-space () для возврата последовательности нормализованных строк
мне нужно использовать функцию XPath normalized-space () для нормализации текста, который я хочу извлечь из документа XHTML:http://test.anahnarciso.com/clean_bigbook_0.html
я использую следующее выражение:
//*[@slot="address"]/normalize-space(.)
который отлично работает в Qizx Studio, инструменте, который я использую для тестирования выражений XPath.
let $doc := doc('http://test.anahnarciso.com/clean_bigbook_0.html')
return $doc//*[@slot="address"]/normalize-space(.)
этот простой запрос возвращает последовательность xs:string
.
144 Hempstead Tpke
403 West St
880 Old Country Rd
8412 164th St
8412 164th St
1 Irving Pl
1622 McDonald Ave
255 Conklin Ave
22011 Hempstead Ave
7909 Queens Blvd
11820 Queens Blvd
1027 Atlantic Ave
1068 Utica Ave
1002 Clintonville St
1002 Clintonville St
1156 Hempstead Tpke
Route 49
10007 Rockaway Blvd
12694 Willets Point Blvd
343 James St
теперь, я хочу использовать предыдущие выражение в моем коде Java.
String exp = "//*[@slot="address""]/normalize-space(.)";
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile(exp);
Object result = expr.evaluate(doc, XPathConstants.NODESET);
но последняя строка вызывает исключение:
Cannot convert XPath value to Java object: required class is org.w3c.dom.NodeList; supplied value has type xs:string
Obvsiously, я должен изменить XPathConstants.NODESET
для чего - то; я пробовал XPathConstants.STRING
но он возвращает только первый элемент последовательности.
как я могу получить что-то вроде массив строк?
спасибо заранее.
4 ответов
ваше выражение работает в XPath 2.0, но является незаконным в XPath 1.0 (который используется в Java) - он должен быть!--1-->.
в любом случае, в XPath 1.0, когда normalize-space()
вызывается на наборе узлов, берется только первый узел (в порядке документа).
чтобы сделать то, что вы хотите сделать, вам нужно использовать парсер, совместимый с XPath 2.0, или пересечь результирующий набор узлов и вызвать normalize-space()
на каждый узел:
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr;
String select = "//*[@slot='address']";
expr = xpath.compile(select);
NodeList result = (NodeList)expr.evaluate(input, XPathConstants.NODESET);
String normalize = "normalize-space(.)";
expr = xpath.compile(normalize);
int length = result.getLength();
for (int i = 0; i < length; i++) {
System.out.println(expr.evaluate(result.item(i), XPathConstants.STRING));
}
...выходы точно ваш данный выход.
Это зависит от того, какую версию XPath вы используете. Проверить этот пост, надеюсь он ответит на ваш вопрос: можно ли применить normalize-space ко всем узлам, которые находит выражение XPath? удачи.
выражение:
//*[@slot="address"]/normalize-space(.)
является синтаксически законным (и практически полезным) выражением XPath 2.0.
то же самое выражение не является синтаксически законным в XPath 1.0 - шаг местоположения не может быть вызовом функции.
на самом деле, невозможно написать один выражение XPath 1.0, результатом оценки которого является требуемый набор строк.
вам нужно использовать в вашей программе a продукт, который реализует XPath 2.0 -- например, Saxon 9.x.
как вы заметили, выражение XPath 2.0 //*[@slot="address"]/normalize-space(.)
возвращает последовательность строк. Этот тип возврата не поддерживается JAXP XPathConstants
класс, потому что интерфейсы JAXP не были разработаны для поддержки XPath 2.0.
это оставляет вам два варианта:
- используйте процессор XPath 2.0, который имеет собственные интерфейсы для XPath 2.0 или преобразование последовательностей в тип возврата, поддерживаемый JAXP
-
использовать только выражения XPath 1.0. Например, в вашем случае вы можете просто выбрать целевые узлы:
//*[@slot="address"]
а затем повторите полученный nodeset, собирая результаты в массив или
List
.
обратите внимание, что важно различать между процессор вы используете для оценки выражения и интерфейс вы используете, чтобы инициировать оценку.