![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Проверить атрибуты в xml-файле
Scott Storch © (2010-11-23 17:45:00)Возникла необходимость проверять наличие атрибутов в xml-файле для определенных нодов. Хранить информацию об атрибутах, по каждому из необходимых мне нодов, пока думаю так:
TStrings.AddObject(<имя нода>, <список атрибутов (TStrings)>)
Алгоритм будет выглядеть примерно так:
// ...
for I := 0 to ChildNodes.Count - 1 do
begin
if list_nodes_for_chk.IndexOf(ChildNodes[I].NodeName) <> -1 then
// это нод для которого необходимо проверить наличие атрибутов
begin
Attrs := TStrings(list_nodes_for_chk.Objects[I]) // извлекаем список атрибутов
// Проверка наличия атрибутов
end;
end;
// ...
Ориентировочно необходимо будет проверять 3-5 нодов, для кажлого из которых 5-7 атрибутов. Городить десяток списков неправильно на мой взгляд, захламляется код. Что посоветуете?
Scott Storch (2010-11-25 12:53:00) [1]Обалдеть как все упрощается. Спасибо
DiamondShark (2010-11-25 12:51:00) [2]А может уж лучше тогда схему написать, и валидировать документ по схеме?
Медвежонок Пятачок (2010-11-25 12:46:00) [3]принцип простейший.
сначала выбираем все узлы из Б
selectnodes('//query')
дальше перебираем полученный список.
получаем выражение проверки и применяем его к документу А.
Но это еще не все.
Какой метод использовать с текущим выражением?
1.Может текущее выражение проверяет наличие обязательного атрибута конкретного узла. Тогда нужен selectsinglenode
2. Может текущее выражение ищет ноды, у которых нет определенного атрибута. Тогда нужно вызывать selectnodes
Далее.
Как следует интерпретировать результат селекта?
Допустим проверяли наличие недопустимого атрибута и получили nil
Но это могла быть и проверка наличия обязательного атрибута.
В первом случае нил - это "хорошо", а во втором случае "хорошо" - это ненил
Поэтому и надо добавить в узел квери два атрибута:
1. какой метод юзать: selectnodes/selectsinglenode
2. как интерпретировать результат метода.
Scott Storch (2010-11-25 12:26:00) [4]не совсем понятно
> а вот это бы убрал бы однозначно:
> for I := 0 to childNodes.length - 1 do
>
> так как здесь идет жесткая привязка алгоритма к структуре
> проверяемого документа
не совсем понятно, можете поправить код, не обязательно, чтобы был рабочий, просто принцип увидеть
Медвежонок Пятачок (2010-11-25 12:15:00) [5]я бы для каждого квери ввел атрибут, который бы говорил, как следует использовать выражение и как интерпретировать результат селекта по его выражению xpath.
например:
- текущий xpath следует использовать в selectsinglenode. если он вернул нил то это ошибка (или наоборт).
- текущий xpath следует использовать в selectnodes. если длина списка не нулевая - это ошибка (или наоборт).
тогда алгоритм проверки сократится и его не надо будет переписывать слишком часто при меняющихся требованиях к структуре проверяемого документа.
а вот это бы убрал бы однозначно:
for I := 0 to childNodes.length - 1 do
так как здесь идет жесткая привязка алгоритма к структуре проверяемого документа
Scott Storch (2010-11-25 12:05:00) [6]Накатал для себя пример, на основе его буду писать алгоритм для своего приложения. Пример вроде работает как надо. Можете посмотреть, может лишнего чего написал или что-то можно упростить.
a.xml
<products>
<book id="7" name="" autor=""/>
<cd id="14" name=""/>
<book id="17" name="" autor=""/>
</products>
b.xml (управляющий)
<products>
<book>
<queries>
<query str="/products/book[not(@id)]"/>
<query str="/products/book[not(@name)]"/>
<query str="/products/book[not(@autor)]"/>
</queries>
</book>
<cd>
<queries>
<query str="/products/cd[not(@id)]"/>
<query str="/products/cd[not(@name)]"/>
</queries>
</cd>
</products>
uses
msxml;
{$R *.dfm}
procedure TForm14.FormCreate(Sender: TObject);
var
xml_doc_a,
xml_doc_b { управляющий xml }: IXMLDOMDocument;
procedure analyze_xml_doc;
var
I, J: Integer;
query_str: string;
xml_node_prods_a, xml_node_prod_a, xml_node_queries, xml_node_query: IXMLDOMNode;
begin
xml_node_prods_a := xml_doc_a.documentElement;
with xml_node_prods_a do
{ для каждого подузла "products" в a.xml проверяем
наличие обязательных атрибутов }
for I := 0 to childNodes.length - 1 do
begin
xml_node_prod_a := childNodes[I];
{ находим в b.xml узел "queries" для соответствующего узла из a.xml }
xml_node_queries := xml_doc_b.selectSingleNode('/products/' +
xml_node_prod_a.nodeName + '/queries');
Assert(xml_node_queries <> nil);
with xml_node_queries do
begin
for J := 0 to childNodes.length - 1 do
begin
xml_node_query := childNodes[J]; // Узел содержащий атрибут с XPath-выражением
query_str := xml_node_query.attributes.item[0].nodeValue; // XPath-выражение
// применяем XPath выражение к узлу из a.xml
Assert(xml_node_prod_a.selectSingleNode(query_str) = nil,
'Ошибка целостности! Отсутствует необходимый атрибут!');
end;
end;
end;
end;
begin
xml_doc_a := CoDOMDocument.Create;
xml_doc_b := CoDOMDocument.Create;
try
Assert(xml_doc_a.load('D:\a.xml'));
Assert(xml_doc_b.load('D:\b.xml')); // загружаем управляющий xml
analyze_xml_doc;
finally
xml_doc_a := nil;
xml_doc_b := nil;
end;
end;
Scott Storch (2010-11-24 14:48:00) [7]круто, спасибо.
Тему можно закрывать
Медвежонок Пятачок (2010-11-24 14:36:00) [8]iList := xdoc.selectNodes('/products/product[not(@id)]');
if iList.length > 0 then
ShowMessage('найдены узлы product, не имеющие атрибута id')
else
ShowMessage('Все узлы product в документе имеют атрибут id');
Без проверки:
Список всех продуктов в документе, у которых есть атрибут "id".
Все прочие продукты просто не принимаем во внимание
iList := xdoc.selectNodes('/products/product[@id]');
Scott Storch (2010-11-24 14:08:00) [9]
> в узлах прописаны выражения xpath.
К примеру:
XML-файл:
<products>
<product id="17" name="Холодильник Miele KFNS 4929 SDE ed"/>
<product id="18" name="Утюг с парогенератором Philips GC8260">
</products>
Можете привести пример выражения, касательно проверки атрибута (к примеру в узле "product" нужно проверить наличие атрибута "id").
"/products/product/id<что дальше?>"
Только начал разбираться, не совсем все понятно, пример бы все прояснил.
Scott Storch (2010-11-24 00:00:00) [10]
> во первых в случае стринглиста файл тоже ниоткуда не возьмется.
> его надо будет распространятьво вторых, в случае, когда
> он будет xml документом его можно иметь в виде:1. локальный
> дисковый файл2. ресурс в exe/dll и загрузка через протокол
> res://3. ресурс в сети или инете и загрузка его по шттп
> через url
Хранить ввиде ресурса я как-то не подумал. Как раз то, что надо. Спасибо.
Медвежонок Пятачок (2010-11-23 23:49:00) [11]во первых в случае стринглиста файл тоже ниоткуда не возьмется. его надо будет распространять
во вторых, в случае, когда он будет xml документом его можно иметь в виде:
1. локальный дисковый файл
2. ресурс в exe/dll и загрузка через протокол res://
3. ресурс в сети или инете и загрузка его по шттп через url
Плохиш (2010-11-23 23:48:00) [12]
> Scott Storch (23.11.10 23:31) [4]
Можно озвучить великий смысл этой задачи?
Scott Storch (2010-11-23 23:31:00) [13]
> управляющий файл проверок - xml документ.в нем узлы.в узлах
> прописаны выражения xpath. грузим управляющий файл
При таком подходе управляющий файл нужно будет распространять вместе с приложением, верно?. А что, если пользователь модифицирует содержимое управляеющего файла или вообще удалит его.
Медвежонок Пятачок (2010-11-23 22:43:00) [14]пример чего?
управляющий файл проверок - xml документ.
в нем узлы.
в узлах прописаны выражения xpath.
грузим управляющий файл, получаем список узлов.
проходим по списку, читаем выражения xpath.
в проверяемом документе делаем selectsinglenode с уазанным xpath
если он вернул не нулл, идем дальше.
если селект вернул нулл, значит в проверяемом документе отсутствует контролируемый атрибут.
все.
Scott Storch (2010-11-23 18:17:00) [15]
> берем еще один xml файл и пишем в него список xpath котрые
> должны вернуть не нулл.
>
> и все.
> енумерейтим список и делаем селектсинглнод в проверяемом
> документе.
можно простейший пример
Медвежонок Пятачок (2010-11-23 17:54:00) [16]TStrings.AddObject(<имя нода>, <список атрибутов (TStrings)>)
Зачем?
Зачем на болид F1 ставить карбюратор от горбатого запора и батарейное зажигание?
В том смысле что твой стринглист надо еще откуда-то заполнить.
берем еще один xml файл и пишем в него список xpath котрые должны вернуть не нулл.
и все.
енумерейтим список и делаем селектсинглнод в проверяемом документе.