Имя: Пароль:
1C
1С v8
Как удалить узел в XML файле по условию значения определенного атрибута?
,
0 Alginsky
 
03.02.23
23:22
Кто сталкивался с удалением атрибута в XML файле?

Есть такой XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
    <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Target="settings.xml"/>
    <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
    <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering" Target="numbering.xml"/>
    <Relationship Id="rId6" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/>
    <Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" Target="fontTable.xml"/>
    <Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings" Target="webSettings.xml"/>
    <Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer" Target="footer1.xml"/>
</Relationships>

Надо удалить узел по условию если его атрибут "Type" равно http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer

А сейчас это последний узел. Именно по этому условию нужно, по индексу не вариант, так как он может в любом месте списка быть...
Возможно ли это реализовать? Через DOM или Чтение ЗаписьXML, главное не XDTO. Задача как обратный процесс для моей предыдущей темы: Недоступимое имя XML. Двоеточие в имени атрибута не принимает.
1 NorthWind
 
04.02.23
08:34
Ну самое простое - зачитать чтением все подряд и тут же записывать записью, пока не встретите атрибут. Встретите - значит, не записывать.
2 NorthWind
 
04.02.23
08:36
ДОМ, по-моему, тоже дает возможность удалять узлы, но по сути там будет то же чтение и потом запись...
3 eddy_n
 
04.02.23
09:54
Как вариант использовать метод ДОМа УдалитьДочерний(). Это про узлы. Но - только на сервере.
4 eddy_n
 
04.02.23
09:55
Узел.УдалитьДочерний(ДочернийУзел); по твоему условию.
5 ДедМорроз
 
04.02.23
11:40
Дом грузить в память - иногда это будет смертельно для сервера - получите не хватает памяти.
Через SAX в 1с объект ЧтениеXML - читаем,а через запись сразу пишем.
Нашли объект,который нужно удалить,выключаем запись,пока не дойдем до его закрытия.
Если обнаружили открытый дочерний элемент,то просто пишем его в массив и ожидаем закрытие последнего элемента из массива - когда массив пуст,то включаем запись и продолжаем.
Опять же,можно сделать массив вложенности элементов,если нас интересуют условия по родительским элементам.
Получится быстро и просто даже на файлах,которые в память не помещаются.

Я по такому принципу писал выборочное чтение файла обмена.
6 Alginsky
 
04.02.23
12:17
(4) Да, видел этот метод, но как отобрать удаляемый узел? Вот это не смог сделать
7 Alginsky
 
04.02.23
12:23
(5) Я хотел через дом. Потому что с помощью Чтение Запись когда делаешь он удаляет пробелы в некоторых словах документа. Сравнил документы чтобы найти причину, оказалось метод Чтение Запись превращает такую строку - <w:t xml:space="preserve"></w:t> в такую - <w:t xml:space="preserve"/>, из-за этого удаляются пробелы. Есть ли решение для этого? Если есть тогда бы можно было рассмотреть метод который вы написали
8 eddy_n
 
04.02.23
13:07
(6) По имени найти - не вариант? НужныйЭлемент  = ДокументDOM.ПолучитьЭлементыПоИмени("ТотСамыйЭлемент");
9 eddy_n
 
04.02.23
13:10
(8) Имя элемента заранее известно?
10 eddy_n
 
04.02.23
13:15
(8) Имя элемента заранее известно ?
11 Alginsky
 
04.02.23
13:39
(8) Не вариант, там везде же имя "Relationship" и именно по атрибуту "Type" этого элемента нужно отобрать
12 eddy_n
 
04.02.23
14:40
(11) Говоришь - обложили со всех сторон? Ну тогда - как в (1).
13 kittystark
 
04.02.23
15:54
тхт = новый ТекстовыйДокумент();
тхт.Прочитать( имяФайла );
стр = тхт.ПолучитьТекст();    
стр = RegExpReplace( стр, <[^<]+footer[^<]+>", "" );

тхт.УстановитьТекст( стр );
тхт.Записать( имяФайла );

Function RegExpReplace( str, pattern, replacement ) export

    RegExp = new COMObject("vbscript.regexp");
    RegExp.IgnoreCase    = true;
    RegExp.MultiLine    = true;
    RegExp.Global        = true;
    RegExp.Pattern         = pattern;    

    return RegExp.Replace(str,replacement);
        
EndFunction
14 kittystark
 
04.02.23
15:58
поправочка, кавычку упустил
стр = RegExpReplace( стр, "<[^<]+footer[^<]+>", "" );
15 kittystark
 
04.02.23
16:06
а можно так
стр = RegExpReplace( стр, "<[^<]+footer[^>]+>", "" );

или так
стр = RegExpReplace( стр, "<[^<]+schemas.openxmlformats.org\/officeDocument\/2006\/relationships\/footer[^>]+>", "" );
16 ДедМорроз
 
04.02.23
16:33
(7) тут проблема не в преобразователе,а в том,что такие преобразования по стандарту xml допустимы,и оба тега эквивалентны с точки зрения формата xml.
Если нужны пробелы,то их нужно в xml писать как &x20; тогда и преобразования не будет и согласно формату xml это будут значащие символы.
17 NorthWind
 
04.02.23
16:53
(16) вообще, насколько я понял, тег xml:space как раз предназначен для того, чтобы парсер не удалял пробелы в начале и конце строки, чтобы не испортить форматирование, например, в стихах. https://www.w3.org/TR/xml/ Видимо, ТС имеет в виду что ломается как раз эта опция.
18 NorthWind
 
04.02.23
17:01
хотя как на это влияет сокращенное написание тега - не очень понятно. Если верить спецификации, парсер, встретив этот атрибут в элементе, должен поменять правила работы с пробелами для текущего элемента и для всех его потомков. И какая в сущности разница, используется ли сокращенное написание или полное?
19 Архитектор_1С
 
04.02.23
17:03
(0) Рекомендую эти свистопляски с XML-файлами делать через http-сервисы 1С, с которыми можно делать все что угодно в отличии от web-сервисов 1С
20 Alginsky
 
04.02.23
18:35
(19) так я эту функцию как раз через http-сервис использую, не знаю что вы имели ввиду под все что угодно...
Задача у меня такая: Разбираю docx файл, добавляю нижний колонтитул с QR кодом и текстом. С добавлением в docx где нет нижнего колонтитула без проблем работает, уже сделал. Теперь вторая задача у меня удалить нижний колонтитул если имеется, а потом добавить свой. Вот сейчас занимаюсь удалением ссылок старого колонтитула занимаюсь, а там вот такая труба с пробелами и с условными удалениями узла...
21 Alginsky
 
04.02.23
18:36
(13) нее, Com не пойдет, все делается через http-сервис, модули все серверные
22 kittystark
 
04.02.23
19:06
(21) а ты попробуй
23 Alginsky
 
04.02.23
19:34
(22) так COM объекты только на клиенте работают же
Но все равно спасибо, на крайняк текстом мочить буду строки
24 kittystark
 
04.02.23
19:42
я тут недавно боролся с XML помогите с XSLT - замена значения атрибута тэга - не получилось
но код приведенный мной - помог справиться, и поверь работает наСервере
25 NorthWind
 
04.02.23
20:22
(20) так может лучше его не удалять, а очистить/подменить значения атрибутов?
26 eddy_n
 
04.02.23
20:42
(23) Заблуждение.
27 eddy_n
 
04.02.23
20:44
(23) Зарегь компоненту на серверу и работай себе там.
28 eddy_n
 
04.02.23
20:46
(24) И больше нигде ничего не пришлось менять? Только в одном тэге?
29 Alginsky
 
04.02.23
20:54
(16) (18) Нашел решение с проблемой пробелов(7), может кому понадобиться, лечиться одной строкой ЧтениеXML.ИгнорироватьПробелы = Ложь;
После этого не будет ломать пробелы
30 kittystark
 
04.02.23
20:56
(28) да
там задача сводилась к тому, что в УПД для ЭДО поменять "статус - 2" на "статус - 1"

но в той задаче код был такой
стр = RegExpReplace( стр, "Функция\s*=\s*""ДОП""", "Функция=""СЧФДОП""" );
31 eddy_n
 
06.02.23
00:25
(29) Убедительный пример того, что надо просто читать мат. часть. Всё есть, надо только поднять.
32 eddy_n
 
06.02.23
02:44
(13) Чисто под Окна.
33 RomaH
 
naïve
06.02.23
10:16
xpath же?
34 kittystark
 
06.02.23
13:07
(33) научи!
и здесь и по ссылке в (24)
35 RomaH
 
naïve
06.02.23
13:19
ну ... документДОМ
через xpath получаешь требуемые элементы - а дальше делаешь с ними всякое
Программист всегда исправляет последнюю ошибку.