In our new project we have to provide a search functionality to retrieve data from hundreds of xml files. I have a brief of our current plan below, I would like to know your suggestions/improvements on this.
These xml files contain personal information, and the search is based on 10 elements in it for example last name, first name, email etc. Our current plan is to create an master XmlDocument with all the searchable data and a key to the actual file. So that when the user searches the data we first look at master file and get the the results. We will also cache the actual xml files from the recent searches so simillar searches later can be handled quickly.
Our application is a .net 2.0 web application.
asked Feb 19, 2009 at 4:59
First: how big are the xml files? XmlDocument
doesn’t scale to “huge”… but can handle “large” OK.
Second: can you perhaps put the data into a regular database structure (perhaps SQL Server Express Edition), index it, and access via regular TSQL? That will usually out-perform an xpath search. Equally, if it is structured, SQL Server 2005 and above supports the xml
data-type, which shreds data – this allows you to index and query xml data in the database without having the entire DOM in memory (it translates xpath into relational queries).
answered Feb 19, 2009 at 5:02
Marc GravellMarc Gravell
1.0m261 gold badges2548 silver badges2887 bronze badges
4
If you can store then data in a SQL Server database then you could make use of SQL Servers in built XPath query functionality.
answered Feb 19, 2009 at 5:02
Dave BarkerDave Barker
6,2952 gold badges24 silver badges25 bronze badges
Hmm, sounds like your building a database over the top of Xml, for performance I’d be reading those files into the DB of your choice, and let it handle indexing and searching for you. If that’s not an option get really with XPath, or roll your own exhaustive search using XmlReader.
Xml is not the answer to every problem, however clean it appears to be, performance will suck.
answered Feb 19, 2009 at 5:03
MrTellyMrTelly
14.6k1 gold badge48 silver badges81 bronze badges
Index your XML files. Look into http://incubator.apache.org/lucene.net/
I recently used it at my previous job to cache our SQL database for fast searching and very little overhead.
It provides fast searching of content inside xml files (all depending on how you organize your cache).
Very easy and straight forward to use.
Much easier than trying to loop through a bunch of files.
PHeiberg
29.3k6 gold badges59 silver badges81 bronze badges
answered Feb 19, 2009 at 15:26
GautamGautam
2,0751 gold badge24 silver badges24 bronze badges
Why dont you store the searchable data in a database table with key to the actual file? So your search would be on database table rather than xml file. I suppose this would be faster because you may index the table for faster searching.
answered Feb 19, 2009 at 5:04
Nahom TijnamNahom Tijnam
4,6665 gold badges25 silver badges25 bronze badges
I have thousands of xml files in different sub directories under one root folder.
My requirement is to search for a text in all these xml files irrespective of their location in the xml file.
Currently I am using BufferedReader class to read these xml files (my code looks like below)
while ((currentLine = br.readLine()) != null) {
if (currentLine.contains("myTargetString")) {
temp = currentLine;
myArraylist.add(temp );
}
But I know that there should some best way to search through these xml files, but cant figure out the best API or way.
I get one string as an input and my program should be able to search through all the xml files and return the file names. By using this BufferedReader it is taking much time.
Any ideas would be helpful.
asked Jan 12, 2015 at 23:00
MaheshVarmaMaheshVarma
2,0717 gold badges34 silver badges58 bronze badges
1
So there’s two possible solutions you could do here. Firstly for each file, you could parse with an XML paser (there are many API’s for Java) then use something like an xpath query (something like //*[text() = ‘your query’]
to locate an element that matches your text criteria.
Secondly, you could look at what JamesB suggested and go for an indexed solution like Lucene, where for every file in some directory, index those files and then perform a search over them using something likes lucenes search API to find your text string.
answered Jan 13, 2015 at 1:12
If you need to improve the speed and can not use indexes (lucene would be my recommendation), you can filter your input first by using the good old recursive grep command grep -r <searchtext> <path>
. (Link to grep on windows question). And then parsing the resulting files with Java to filter out false positive hits (commented out blocks, matching element names,…). Grep is IMHO the fastest way to find text in a large number of files without an index.
answered Jan 13, 2015 at 9:41
CfxCfx
2,2622 gold badges15 silver badges21 bronze badges
0 / 0 / 0 Регистрация: 26.08.2011 Сообщений: 5 |
|
1 |
|
12.09.2011, 11:23. Показов 6142. Ответов 2
Здравствуйте! Подскажите пожалуйста есть ли возможность поиска внутри файла xml по словам/фразам, с помощью сторонних программ на-подобии виндузового поиска в файлах word’a?
0 |
Programming Эксперт 94731 / 64177 / 26122 Регистрация: 12.04.2006 Сообщений: 116,782 |
12.09.2011, 11:23 |
2 |
3 / 3 / 0 Регистрация: 19.06.2011 Сообщений: 19 |
|
13.09.2011, 15:56 |
2 |
Ctrl+F практически в любом интернет-браузере.
0 |
0 / 0 / 0 Регистрация: 26.08.2011 Сообщений: 5 |
|
13.09.2011, 17:29 [ТС] |
3 |
Другое. В общем нашёл как это можно сделать в WinXP, в Win7 поисковик позволяет это делать без каких-либо проблем. Ещё есть notepad++ и с помощью Total Commander можно искать, но notepad++ бесплатный
0 |
- Печать
Страницы: [1] Вниз
Тема: [РЕШЕНО]поиск текста в файле .xml (Прочитано 2265 раз)
0 Пользователей и 1 Гость просматривают эту тему.
ratte
необходимо сгрепать или как-то ещё найти ряд параметров.
именно- что идёт за символами <keybind key= потом за <execute> и так от начала документа до конца, то есть если в доке есть
<keybind key="W-k">
<action name="Execute">
<execute>avidemux</execute>
</action>
</keybind>
<keybind key="W-space">
<action name="Execute">
<execute>gnome-terminal</execute>
</action>
</keybind>
<keybind key="XF86Search">
<action name="Execute">
<execute>epiphany</execute>
</action>
</keybind>
то вывод должен быть таким
W-k - avidemux
W-space - gnome-terminal
XF86Search - epiphany
реально ли?
« Последнее редактирование: 05 Января 2011, 21:57:52 от ratte »
ende_neu
>реально ли?
Конешно!Питон – Beautiful Soup, libxml етц.Куча парсеров.
ArcFi
ratte
почитал и понял что наверное проще конвертировать xml в txt и использовать grep, но не понял как два шаблона или вывести искомые строки с тремя за ними следующими.
всё. разобрался. спасибо.
« Последнее редактирование: 05 Января 2011, 21:55:40 от ratte »
ploop
конвертировать xml в txt
А в чём разница между ними?
ratte
уже разобрался. спасибо всем. grep работает и с xml отлично. ключи тоже нашел.
Чистый
строчку кода в студию а то как бы и решено а решения на поверхности нет надо копаться
Тестовый репозиторий kdeNeur ppa:devcode/kdeneur
各々が死ぬことをどのように決定する
- Печать
Страницы: [1] Вверх
Язык разметки XML с самого первого стандарта окружает пользователей компьютеров. Таблицы в Excel, выгрузки из интернет-магазинов, RSS-ленты с новостями — все это основано на XML. Хоть визуальное отображение отличается на устройствах и в программах, но в основе всегда лежит единый формат.
Внутри XML-файла может находиться огромное количество информации, поэтому и встает вопрос о перемещении и выборке внутри документа. Как это сделать быстро? Какие средства применять, чтобы в интернет-магазине найти нужный товар из десятков тысяч других? Для навигации и поиска внутри XML используется язык запросов XPath.
В этой статье разберем:
- для кого может быть полезен XPath
- базовые конструкции языка для поиска информации в XML
- чем XPath отличается от CSS-селекторов при поиске в HTML
- Синтаксис XPath
- Отличия от CSS-селекторов
- Кому нужен Xpath
- Заключение
Синтаксис XPath
Для начала создадим базовый пример XML, с которым и будем работать весь урок. Например, список курсов по верстке на Хекслете в XML будет выглядеть так:
<?xml version="1.0" encoding="UTF-8"?>
<courses>
<title>Курсы HTML и CSS (верстка)</title>
<description>На курсах по верстке вы познакомитесь с основами HTML и CSS, научитесь верстать адаптивные страницы, работать с препроцессорами. Освоите современные технологии и инструменты, включая Flex, Sass, Bootstrap.</description>
<course>
<name>Основы современной верстки</name>
<tags>HTML5, CSS, DevTools, верстка</tags>
<duration value="9">9 часов</duration>
<url lang="ru">https://ru.hexlet.io/courses/layout-designer-basics</url>
<url lang="en">https://hexlet.io/courses/layout-designer-basics</url>
</course>
<course>
<name>Основы верстки контента</name>
<tags>CSS3, HTML5, Селекторы, Доступность, CSS Columns, CSS Units, Верстка</tags>
<duration value="18">18 часов</duration>
<url lang="ru">https://ru.hexlet.io/courses/css-content</url>
<url lang="en">https://hexlet.io/courses/css-content</url>
</course>
<course>
<name>Bootstrap 5: Основы верстки</name>
<tags>Bootstrap 5, Адаптивность, HTML, CSS3</tags>
<duration value="10">10 часов</duration>
<url lang="ru">https://ru.hexlet.io/courses/bootstrap_basic</url>
<url lang="en">https://hexlet.io/courses/bootstrap_basic</url>
</course>
</courses>
Это учебный пример, но для отработки навыков XPath подойдет и любой другой XML. Принципы XPath сохранятся при любой структуре файла, потому что по стандарту XML можно использовать элементы с произвольными тегами.
Для тестирования результата подойдут такие онлайн-сервисы, как:
- Code Beautify
- XPather
Абсолютные пути
Самый простой запрос состоит из обращения к корневому элементу. Для этого достаточно выполнить запрос /courses
. Нам вернется XML в почти таком же виде, что и в примере выше. Обратите внимание на строку <?xml version="1.0" encoding="UTF-8"?>
. Она отличается, потому что элемент не внутри <courses>
:
<courses>
<title>Курсы HTML и CSS (верстка)</title>
<description>На курсах по верстке вы познакомитесь с основами HTML и CSS, научитесь верстать адаптивные страницы, работать с препроцессорами. Освоите современные технологии и инструменты, включая Flex, Sass, Bootstrap.</description>
<course>
<name>Основы современной верстки</name>
<tags>HTML5, CSS, DevTools, верстка</tags>
<duration value="9">9 часов</duration>
<url lang="ru">https://ru.hexlet.io/courses/layout-designer-basics</url>
<url lang="en">https://hexlet.io/courses/layout-designer-basics</url>
</course>
<course>
<name>Основы верстки контента</name>
<tags>CSS3, HTML5, Селекторы, Доступность, CSS Columns, CSS Units, Верстка</tags>
<duration value="18">18 часов</duration>
<url lang="ru">https://ru.hexlet.io/courses/css-content</url>
<url lang="en">https://hexlet.io/courses/css-content</url>
</course>
<course>
<name>Bootstrap 5: Основы верстки</name>
<tags>Bootstrap 5, Адаптивность, HTML, CSS3</tags>
<duration value="10">10 часов</duration>
<url lang="ru">https://ru.hexlet.io/courses/bootstrap_basic</url>
<url lang="en">https://hexlet.io/courses/bootstrap_basic</url>
</course>
</courses>
В качестве результата XPath возвращает узлы XML-документа.
Продолжим цепочку и обратимся к описанию из элемента <description>
. Для этого добавим в запрос путь к description
: /courses/description
. Результатом выполнения станет:
<description>На курсах по верстке вы познакомитесь с основами HTML и CSS, научитесь верстать адаптивные страницы, работать с препроцессорами. Освоите современные технологии и инструменты, включая Flex, Sass, Bootstrap.</description>
Путь, который строится от корневого элемента, называется абсолютным. Используем схему из прошлого запроса и обратимся к любому элементу внутри XML.
Попробуем обратиться к имени курса. В этом случае вернется поле <name>
из всех курсов. Запрос /courses/course/name
вернет:
<name>Основы современной верстки</name>
<name>Основы верстки контента</name>
<name>Bootstrap 5: Основы верстки</name>
Вот список некоторых базовых запросов и их результат:
Запрос | Результат |
---|---|
/courses/course |
Все данные из всех элементов <course></course> |
/courses/course/name |
<name>Основы современной верстки</name> <name>Основы верстки контента</name> <name>Bootstrap 5: Основы верстки</name> |
/courses/course/duration |
<duration value="9">9 часов</duration> <duration value="18">18 часов</duration> <duration value="10">10 часов</duration> |
Относительные пути
Прошлые запросы строились с помощью абсолютных путей — то есть мы указывали полный путь до информации. Бывают ситуации, когда полный путь не подходит: например, мы хотим обраться к какому-то уникальному полю или не знаем полный путь. В этом случае можно использовать относительный путь — он произведет поиск по всему XML и вернет узлы, подходящие под запрос.
Чтобы записать относительный путь, нужно использовать конструкцию //
. После нее можно написать любое поле и получить результат. Например, //name
вернет поля <name>
из всего XML:
<name>Основы современной верстки</name>
<name>Основы верстки контента</name>
<name>Bootstrap 5: Основы верстки</name>
Проблема такого подхода — уникальность полей. В документах одни и те же имена полей могут обозначать разные данные в зависимости от расположения. Поэтому используйте относительные пути только там, где уверены в возвращаемых данных. Например, в нашем примере название курса может быть заключено в <title>
:
<courses>
<title>Курсы HTML и CSS (верстка)</title>
<!-- ... -->
<course>
<title>Основы современной верстки</title>
<!-- ... -->
</course>
<course>
<title>Основы верстки контента</title>
<!-- ... -->
</course>
<course>
<title>Bootstrap 5: Основы верстки</title>
<!-- ... -->
</course>
</courses>
Запрос //title
вернет не только имена курсов, но и узел, который находится в <courses>
:
<title>Курсы HTML и CSS (верстка)</title>
<title>Основы современной верстки</title>
<title>Основы верстки контента</title>
<title>Bootstrap 5: Основы верстки</title>
Чтобы сэкономить пару секунд, разработчики опускают корневой элемент и пользуются относительными путями. Например, вместо /courses/course/name
они пишут //course/name
. Для практики попробуйте прошлые примеры перевести на относительные пути с помощью такого механизма.
Несколько примеров запросов с идентичными ответами, как и в прошлой таблице:
Запрос | Результат |
---|---|
//course |
Все данные из всех элементов <course></course> |
//name |
<name>Основы современной верстки</name> <name>Основы верстки контента</name> <name>Bootstrap 5: Основы верстки</name> |
//course/duration |
<duration value="9">9 часов</duration> <duration value="18">18 часов</duration> <duration value="10">10 часов</duration> |
Предикаты
В примерах запросов к именам возвращались имена всех найденных курсов. В некоторых ситуациях это может быть избыточно. Что делать, если хочется получить данные только по первому курсу в <courses>
? На помощь приходят предикаты — конструкции, с помощью которых можно отфильтровать элементы по заданным условиям.
Выберем ключевые слова первого курса по верстке. Для этого достаточно использовать запрос //course[1]/tags
:
<tags>HTML5, CSS, DevTools, верстка</tags>
Обратите внимание на[1]
. Это предикат с таким условием: «Взять элемент по индексу 1». Попробуйте сделать запрос ко второму или третьему элементу. Достаточно поменять всего одну цифру!
В XPath индексы элементов начинаются с единицы, а не с нуля, как в принятых стандартах программирования. Если вы уже программируете, это может немного запутать.
Предикаты помогают делать точные выборки. Например, получить ссылки на русскоязычные страницы курсов. Для этого нужно получить элементы <url>
, у которых атрибут lang
равен ru
. Делается это указанием атрибута и значения. Чтобы XPath отличил атрибут от элемента перед атрибутом указывается символ @
.
Теперь запрос будет выглядеть так: //course/url[@lang="ru"]
<url lang="ru">https://ru.hexlet.io/courses/layout-designer-basics</url>
<url lang="ru">https://ru.hexlet.io/courses/css-content</url>
<url lang="ru">https://ru.hexlet.io/courses/bootstrap_basic</url>
Иногда полезно выбрать элементы, которые имеют хоть какой-то атрибут. Для этого можно использовать конструкцию //*[@*]
:
<duration value="9">9 часов</duration>
<url lang="ru">https://ru.hexlet.io/courses/layout-designer-basics</url>
<url lang="en">https://hexlet.io/courses/layout-designer-basics</url>
<duration value="18">18 часов</duration>
<url lang="ru">https://ru.hexlet.io/courses/css-content</url>
<url lang="en">https://hexlet.io/courses/css-content</url>
<duration value="10">10 часов</duration>
<url lang="ru">https://ru.hexlet.io/courses/bootstrap_basic</url>
<url lang="en">https://hexlet.io/courses/bootstrap_basic</url>
По примеру выше видно, знак *
обозначает «все/любой».
Когда выбраны элементы по атрибутам, можно произвести дополнительную фильтрацию по этим значениям. Например, найдем элементы <duration>
со значением атрибута value
больше 9
. Внутри предикатов используются операторы сравнения, знакомые по языкам программирования:
>
— больше<
— меньше>=
— больше или равно<=
— меньше или равно=
— равно!=
— не равно
Запрос будет выглядеть так: //course/duration[@value > 9]
:
<duration value="18">18 часов</duration>
<duration value="10">10 часов</duration>
Мы разобрались, как выбирать одно поле — это интересная, но редкая задача. Чаще разработчики обрабатывают данные по всему файлу или нескольким полям. Попробуем одновременно использовать предикат и обратиться к другим полям. Обратите внимание на два момента:
- Предикат необязательно должен идти в конце запроса
- Внутри предиката могут находиться новые пути, которые нужно проверить
Мы уже знаем, как с помощью предиката отфильтровать данные по полю <duration>
. Эту задачу мы выполняли с помощью конструкции duration[@value > 9]
. А теперь попробуем сделать эту конструкцию предикатом для <course>
. Так мы получим данные о курсах с длительностью больше 9 часов: //course[duration[@value > 9]]
:
<course>
<title>Основы верстки контента</title>
<tags>CSS3, HTML5, Селекторы, Доступность, CSS Columns, CSS Units, Верстка</tags>
<duration value="18">18 часов</duration>
<url lang="ru">https://ru.hexlet.io/courses/css-content</url>
<url lang="en">https://hexlet.io/courses/css-content</url>
</course>
<course>
<title>Bootstrap 5: Основы верстки</title>
<tags>Bootstrap 5, Адаптивность, HTML, CSS3</tags>
<duration value="10">10 часов</duration>
<url lang="ru">https://ru.hexlet.io/courses/bootstrap_basic</url>
<url lang="en">https://hexlet.io/courses/bootstrap_basic</url>
</course>
Можно продолжить этот запрос и получить только имена курсов. Тогда предикат будет в середине запроса, а не в его конце: `//course[duration[@value > 9]]/name
<name>Основы верстки контента</name>
<name>Bootstrap 5: Основы верстки</name>
Функции
В прошлых примерах запросы затрагивали теги и атрибуты. Сами данные мы не затрагивали, хотя это огромный пласт информации, по которой можно делать выборки. Для решения этой задачи используются встроенные в XPath функции. Они являются частью предикатов — например, @
. Попробуем найти курс с названием «Основы верстки контента».
Для поиска по тексту внутри элемента используется функция text()
. Ее задача — получить текстовое значение элемента и сравнить его с условием по необходимости. Вот как будет выглядеть запрос для поиска курса с нужным именем: //course[name[text()="Основы верстки контента"]]
<course>
<name>Основы верстки контента</name>
<tags>CSS3, HTML5, Селекторы, Доступность, CSS Columns, CSS Units, Верстка</tags>
<duration value="18">18 часов</duration>
<url lang="ru">https://ru.hexlet.io/courses/css:content</url>
<url lang="en">https://hexlet.io/courses/css:content</url>
</course>
Но что, если нам известно только часть названия? Для этого существует функция contains()
, которая принимает два аргумента:
- Строка, где будет производиться поиск
- Подстрока, которая будет искаться
Для примера найдем курс, у которого в ключевых словах есть слово «Bootstrap». Функция примет текстовое значение элемента tags
и найдет там слово «Bootstrap»: //course[tags[contains(text(), "Bootstrap")]]
<course>
<name>Bootstrap 5: Основы верстки</name>
<tags>Bootstrap 5, Адаптивность, HTML, CSS3</tags>
<duration value="10">10 часов</duration>
<url lang="ru">https://ru.hexlet.io/courses/bootstrap_basic</url>
<url lang="en">https://hexlet.io/courses/bootstrap_basic</url>
</course>
В стандарте XPath существует еще несколько функций, но цель статьи — показать принципы работы тех или иных механизмов, а не дать исчерпывающую документацию по всему языку.
Отличия от CSS-селекторов
Если вы писали на JavaScript, то знаете, что элементы можно искать с помощью CSS-селекторов, используя методы querySelector()
или querySelectorAll()
. Почему же разработчики иногда ищут элементы внутри HTML именно с помощью XPath?
Дело в концепции поиска элементов. Используя CSS, можно идти только в глубину без возможности обратиться к родительским элементам. В отличие от CSS, XPath позволяет в любой момент обращаться и к дочерним, и к родительским элементам.
Если вы хотите подробнее изучить поиск по HTML с помощью XPath, рекомендуем обратиться к статье Introduction to using XPath in JavaScript.
С помощью CSS нельзя найти все элементы div
, внутри которых есть ссылки — можно найти сами ссылки, но не их родителей. XPath позволяет это сделать простым сочетанием div[a]
. Постепенно ситуация меняется: в CSS появился селектор :has()
, но он поддерживается еще не всеми новыми версиями браузеров. Со временем это изменится, но пока реальность именно такая.
Другой пример — поиск элементов по тексту внутри них. С этой задачей CSS никогда не справится, так как такой цели у него нет. XPath, как мы изучили, умеет это делать с помощью функции text()
.
Кому нужен Xpath
Если коротко, Xpath нужен всем, кто работает с XML.
Чтобы разобраться подробнее, изучим несколько примеров:
SEO-специалисты. Специалисты по продвижению часто обрабатывают большие массивы данных и вытаскивают информацию со страниц сайта.
Например, для них критичны мета-теги — дополнительная информация, в которой содержатся иконки сайтов, название страницы, описание и так далее. Эту информацию SEO-специалист может автоматически парсить с помощью запросов в XPath.
Тестировщики. При работе с Front-end тестировщики часто проверяют тот или иной вывод информации на странице — для этого они выбирают отдельные элементы с нужной страницы. Это можно делать через XPath и DevTools, встроенный в браузеры на основе Chromium.
Разработчики. Они часто используют парсеры — это скрипты, которые ищут нужную информацию на страницах одного или нескольких сайтов. Например, мы хотим сравнить стоимость одного и того же товара в разных магазинах. Для такой задачи можно написать скрипт, который пройдется по всем нужным сайтам, сравнит цены и вернет данные. В этом случае для поиска информацию на странице можно использовать XPath.
Это лишь часть сценариев, в которых пригождается язык XPath — на самом деле, их десятки.
Заключение
В этой статье мы рассмотрели, где встречается XML и кому он может пригодиться. Мы научились составлять базовые запросы и изучили часто используемые конструкции XPath:
- Абсолютные и относительные пути
- Предикаты
- Поиск по атрибутам
- Операторы сравнения
- Функции
Также теперь вы знаете, что поиск по HTML с помощью XPath может быть эффективнее поиска с помощью CSS-селекторов.
В этой статье мы постарались дать знания, которые помогут справиться с большинством задач. Но это далеко не все возможности XPath — это более глубокий язык, чем представлено в статье. Как и с другими технологиями, тут важно набить руку. Чем больше вы практикуетесь, тем более точные и полезные запросы пишете.