Просмотр полной версии : Алгоритм поиска подстроки в XML
marat_sa
07.11.2008, 17:32
Здравствуйте, подскажите пожалуйста, функцию, которая получает некую строку и искала бы совпадения по всем элементам существующего XML, а потом возвращала бы массив путей(массивов) в виде индексов узлов XML дерева до элементов с совпадением %)
public function searchStringInXML(string:String):Array
{
???
}
Например, в такой XML:
var someXML:XML = <xml>
<someNode>
<node1 value1="первый узел" value2="первый подузел"/>
<node2 value1="первый узел" value2="второй подузел"/>
</someNode>
<someNode>
<node1 value1="первый узел" value2="первый подузел"/>
<node2 value1="второй узел" value2="второй подузел"/>
<node3 value1="санузел" value2="второй санузел"/>
</someNode>
</xml>
Делаем
trace(searchStringInXML("второй").toString());
Output: [0, 1], [1, 1], [1, 1], [1, 2]
Получили массив путей до узлов, в аттрибутах которых встречается слово "второй". [0, 1] - первый узел, второй подузел... и т.д.
Пробовал через вложенные 2 цикла for писать с временной xml, потом вконец запутался. Помогите, пожалуйста :rolleyes:
для этого конкретного расклада
public function searchStringInXML(string:String):Array
{
var res:Array = [];
var level0:int = 0;
for each(var node:XML in someXML.*)
{
var level1:int = 0;
for each(var subNode:XML in node.*)
{
for each( var attr:String in subNode.@* ) {
if (attr.indexOf(string) != -1)
{
res.push([level0, level1]);
}
}
level1++;
}
level0++;
}
return res;
}
По-моему, проще оперировать всё-таки с XMLList, предварительно добавив идентификаторы:
var someXML:XML = <xml>
<someNode>
<node1 value1="первый узел" value2="первый подузел"/>
<node2 value1="первый узел" value2="второй подузел"/>
</someNode>
<someNode>
<node1 value1="первый узел" value2="первый подузел"/>
<node2 value1="второй узел" value2="второй подузел"/>
<node3 value1="санузел" value2="второй санузел"/>
</someNode>
</xml>;
someXML..*.(parent().children()[childIndex()].@id = (parent().hasOwnProperty('@id') ? parent().@id.toString()+'_' : '') + childIndex());
var list:XMLList = someXML..*.((attributes().(toString().indexOf('второй') >= 0)).length() > 0);
trace(list.toXMLString());
Но если очень хочется массивы с путями (для редкостных извращенцев), то добавить к вышенаписанному:
var arr:Array = new Array();
var tmp:Array;
list.(hasOwnProperty('@id') && (tmp = @id.toString().split('_')) && (tmp.map(function(item, index, array) { return (parseInt(item)) } )) && arr.push(tmp));
tmp = null;
trace(arr.join('::'));
marat_sa
08.11.2008, 17:56
__etc, код очччччень "читабельный". Но зато кратко и понятно)))
А если, у меня аттрибуты не только id, а разные?
C этим понятно
someXML..*.(parent().children()[childIndex()].@* = ...
А как быть с
(parent().hasOwnProperty('@id')...
Я не понял вопроса. Что значит разные? Это новые дополнительные аттрибуты, с определенным именем.
marat_sa
08.11.2008, 18:13
Че-то да... Это я не понял ответа вашего %)
Все работает прекрасно.
Меня строка смутила:
> По-моему, проще оперировать всё-таки с XMLList, предварительно добавив идентификаторы:
Я думал в исходную someXML добавить имя всех аттрибутов id.
А потом код просмотрел хорошо и разобрался. Спасибо
Но я бы не стал использовать это прям в таком виде, конечно :)
marat_sa
08.11.2008, 18:25
Ну понятно, мне просто принцип был важен. Скелет, так сказать, для опытов и изучения.
Спрошу тогда сразу, чтоб темы не создавать.
Вот делаем мы поиск: indexOf('второй')
Но мы получаем поиск, чувствительный к регистру букв.
Как сделать нечувствительный? Юзать RegExp?
Ну и соответственно wholeWord и прочие стандартные настройки поиска?
Ну сделайте RegExp, как угодно.
BlooDHounD
09.11.2008, 03:30
а может просто сделать toLowerCase? побыстрее будет чем RegExp ...
Ну если только нечувствительный к регистру, то да. А потом можно и регулярки прикрутить :)
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.