• Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

  • CTF с учебными материалами Codeby Games

    Обучение кибербезопасности в игровой форме. Более 200 заданий по Active Directory, OSINT, PWN, Веб, Стеганографии, Реверс-инжинирингу, Форензике и Криптографии. Школа CTF с бесплатными курсами по всем категориям.

изменить значение в Xml файле

  • Автор темы pbnoob
  • Дата начала
P

pbnoob

Доброго дня!

задача не очень сложна: изменить 1значение в XML файле. код на 90% взял из хэлпа, так как это мой первый опыт работы с XML.
Код:
(Declaration)
Dim domParser As NotesDOMParser
Dim LF As String

Sub Initialize
Dim session As NotesSession
Dim db As NotesDatabase
Dim inputStream As NotesStream, outputStream As NotesStream
Dim docNode As NotesDOMDocumentNode

Dim origXML As String, outputFile As String
origXML = "c:\1\10412_03.xml"
outputFile = "c:\1\01.txt"

Dim header As String
header = "Walk Tree agent"
LF = Chr(13)+Chr(10)

On Error Goto errh

Set session = New NotesSession	
Set db = session.CurrentDatabase

'create the output file
Set outputStream =session.CreateStream
outputStream.Open (outputFile)
outputStream.Truncate

'write report title
outputStream.WriteText ("DOM Parser Report - " )
outputStream.WriteText (header+LF)

'open the XML file
Set inputStream = session.CreateStream
inputStream.Open (origXML)
If inputStream.Bytes = 0 Then
outputStream.WriteText (origXML+" is empty"+LF)
Goto results
End If

'create DOM parser and process
Set domParser=session.CreateDOMParser(inputStream, outputStream)
domParser.Process

Stop

'get the document node
Set docNode = domParser.Document

Call walkTree2(docNode)

results:
Call inputStream.Close
Call outputStream.Close
Exit Sub
errh:
outputStream.WriteText ("errh: "+Cstr(Err)+": "+Error+LF)
Resume results
End Sub


Sub walkTree2(node As notesdomnode)
Dim child As notesdomnode
Dim elt As notesdomnode
Dim txt_elt As NotesDOMTextNode
Dim attrs As notesdomnamednodemap
Dim a As notesdomattributenode
Dim piNode As Notesdomprocessinginstructionnode

Dim numChildNodes As Integer

Dim i As Integer
Dim v

LF = Chr(13)+Chr(10)

Set par01=Null

Set child=node.FirstChild
Do While (Lcase(child.NodeName)<>"xfdl")
Set child=child.NextSibling	
Loop 
Set elt=child

Set child=elt.FirstChild
Do While (Lcase(child.NodeName)<>"globalpage")
Set child=child.NextSibling	
Loop 
Set elt=child

Set child=elt.FirstChild
Do While (Lcase(child.NodeName)<>"global")
Set child=child.NextSibling	
Loop 
Set elt=child

Set child=elt.FirstChild
Do While (Lcase(child.NodeName)<>"xformsmodels")
Set child=child.NextSibling	
Loop 
Set elt=child

Set child=elt.FirstChild
Do While (Lcase(child.NodeName)<>"xforms:model")
Set child=child.NextSibling	
Loop 
Set elt=child

Set child=elt.FirstChild
Do While (Lcase(child.NodeName)<>"xforms:instance")
Set child=child.NextSibling	
Loop 
Set elt=child

Set child=elt.FirstChild
Do While (Lcase(child.NodeName)<>"data")
Set child=child.NextSibling	
Loop 
Set elt=child

Set child=elt.FirstChild
Do While (Lcase(child.NodeName)<>"startpage")
Set child=child.NextSibling	
Loop 
Set elt=child

Set child=elt.FirstChild
Do While (Lcase(child.NodeName)<>"formid")
Set child=child.NextSibling	
Loop 
Set elt=child

' вот тут теперь типа замена или что-то типа того
Stop
Set txt_elt=elt.FirstChild ' дошел до нужной ноды со значением -1

'txt_elt.NodeValue="15"
'v=txt_elt.NumberOfChildNodes
'v=elt.NodeType
txt_elt.NodeValue="15" ' надо поменять к примеру на 15

'Set txt_elt=child

'txt_elt.NodeValue="12"

Stop
End Sub

проблема состоит в том, что значение не изменяется. я даже не уверен, что вообще сохраняю XML файл. подскажите плиз как сделать правильно.
 
A

alik86

Noob, в Вашем примере на выходе получается текстовый файл-отчет (вроде как - я поленился изучить его полностью и глянул лишь между строк). А Вы хотите, как я понимаю, поменять файл который подаете на вход, причем изменения пытаетесь внести именно в InputStream (насколько я знаю, в Stream можно делать WriteText, но там нет ничего типа ReplaceText). Если Вы задумали использовать дхловсий парсинг, то и результат пишите в OutputStream и ищите его там (т.е. на выходе, а не на входе).
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 933
609
BIT
177
alik86 ДОМ не отобразит изменения, в потоке, без Serialize
 
A

alik86

lmike, ну это уже следующий вопрос. Человек-то, по-моему, пытается вносить и искать изменения в intput`е.
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 933
609
BIT
177
сам ДОМ - это обект в памяти, в нем нет стримов...

Добавлено: а чтобы поменять его - можно воспользоваться постпроцессингом (чтобы заново не оборачивать в запись потока)
и вот тама - делаем Serialize
после чего - изменения попадут в output
я потому и рекомендовал посмотреть пример

Добавлено:
Код:
 'get the document node
Set docNode = domParser.Document

Call walkTree2(docNode)
здеся уже всё закончилось (нет ни чтения ни записи в стрим), уже просто объект в памяти
 
P

pbnoob

Для alik86
Да, так как мне текстовый отчет не нужен, то возможно я действительно пытался править InputStream

На выходе я тоже вроде как должен получить XML-файл просто с измененным значением. Поэтому прошу совета хотя в общих чертах расписать, что нужно ставить на входе\выходе. Обязательно ли использование Stream для работы с XML? как правильно использовать Serialize?
Потому как в функции walkTree2 я просто "иду" до нужного нода и сразу там же пытаюсь его переписать.
 
A

alik86

Вообще говорят, что да, что NotesXSLTransformer для таких целей очень хорошо подходит, но меня всю дорогу смущала необходимость прикручивать еще и styleSheet (ну а если уж быть до конца честным, то у меня так и не дошли руки до практического применения XSLT -- в этом вопросе я лишь теоретик :) ). Я бы, наверное, ввиду своей лени пошел бы по деревянному пути, а именно, прошёлся бы по всем элементам дерева DOM или по всем событиям SAX и, анализируя нужные места, записал бы желаемый xml в output - как то так.
А на вход парсеров подается то, что нужно отпарсить, на выход кидаем желаемый результат парсинга (прямо как в ТАУ) и это не обязательно стримы - подробности имеются в дизайнерском хелпе (раздел Using XML with LotusScript).

Добавлено: Может тут что-нибудь полезное вычитаете
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 933
609
BIT
177
как правильно использовать Serialize?
открыть пример, на котю я дал ссылку или искать в гугле
Serialize использовать в процедуре PostProcessing
вот до этого domParser.Process
надо зарегать On Event... (названия эвента нет под рукой) с именем процедуры, в кот. меняется ДОМ
после сериалайз - результат будет в output (в примере выше - стрим)
 
P

pbnoob

Спасибо все кто старался помочь. :lovecodeby:

По факту воспользовался советом alik86. На выход поставил пустой XML-файл и функцией wlakTree просто копировал все ноды и в нужный момент просто подставил измененный. Благо все решилось без класса NotesXSLTransformer, метода Serialize и всего остального. Если что, могу выложить код. :)
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 933
609
BIT
177
Если что, могу выложить код.
вы поступили (как бы сказать) не тем способом, как обычно решаются эти задачи, а потому ценность вашего кода - только для вас :rolleyes:
мало того что на ДОМ (построение) было сожрано время и память, дык еще повторно сканируется всё дерево
расточительное, по ресурсам, программирование врядли можно приветствовать
 
A

alik86

Зато не пришлось XSLT-таблицу прикручивать. Да и кто его знает, какие объёмы xml переваривались и т.д. и т.п.
А DOM, как не крути, - штука хорошая.
И вообще, Noob, не слушайте lmike'а, он Вас плохому научит: сначала XSLT, а потом на яву подсадит. (шутка) :rolleyes:
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 933
609
BIT
177
А DOM, как не крути, - штука хорошая.
можно почитать в тырнете - область применения
люди не дураки раз придумывали SAX, XSLT...
ДОМ - большое потребление памяти, время на создание, необходимость внесения изменений на "языке программирования", + удобство работы на "языке программирования"
XSLT - всё как у ДОМ за иключ. языка программирования (он и есть XSL) т.е. пишем прогу и больше её не трогаем (всё остальное можно делать на XSL)
SAX - работа с потоком целиком, необходимость внесения изменений на "языке программирования", + минимальное потребление памяти

есть "промежуточные" решения/реализации, с элементами указанных подходов
 
P

pbnoob

Благодарю еще раз, но действительно я сделал так как сделал.
Другие советы я либо не понял, либо неправильно применил :ya_lamo: . В дальнейшем при работе в XML форматом есть 2 варианта, либо я действительно разберусь, либо просто просто будет узкоспециализированный топорный код. :)
 

seoman2

Green Team
17.02.2010
499
1
BIT
15
Аналогичная задача - заполнить в входную XML-ку в нужные мне теги значения с полей дока.
strm - в потоке XML-ка для редактирования.
Set domParser=session.CreateDOMParser(strm, outputStream)
Пока кроме как в outputStream записать через дерево dom все элементы, узлы и атрибуты, заменяя иногда нужные - не вижу (( тему перечитал.

Я могу же NotesDOMNode.NodeValue дать значение, а потом по новой как то сохранить NotesDOMNode - объект dom в файл?
 
Последнее редактирование:

garrick

Lotus Team
26.10.2009
1 349
151
BIT
164
Аналогичная задача - заполнить в входную XML-ку в нужные мне теги значения с полей дока.
strm - в потоке XML-ка для редактирования.
Set domParser=session.CreateDOMParser(strm, outputStream)
Пока кроме как в outputStream записать через дерево dom все элементы, узлы и атрибуты, заменяя иногда нужные - не вижу (( тему перечитал.

Я могу же NotesDOMNode.NodeValue дать значение, а потом по новой как то сохранить NotesDOMNode - объект dom в файл?
Ну, сказали же SAX или XLST. Ну, почему же опять DOM?
 

seoman2

Green Team
17.02.2010
499
1
BIT
15
измененное дерево сохраняется
Смотрел пример, так и не понял ничего....
Вот я делаю в кнопке так:

Set domParser=session.CreateDOMParser(strm, outputStream)
Call domParser.Serialize( )
domParser.Process
Set docNode = domParser.Document
Call XMLTree(docNode, outputStream)

Set docNode = domParser.Document
и тут уже в нужном мне узле вижу исходное значение, а не "значение1".

в функции XMLTree, в нужном мне узле делаю
docNode.FirstChild.NodeValue = "значение1".
 

seoman2

Green Team
17.02.2010
499
1
BIT
15
Ну, сказали же SAX
NotesSAXParser мне не подойдет, теги в дереве могут повторятся. Да и так глянул, у NotesSAXParser есть только метод Output, значит он пишет в другой файл все узлы? А мне надо замена pyfxtybq, а не генерация по всем узлам нового xml.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!