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

pbnoob

Well-known member
25.08.2006
135
0
#1
Доброго дня!

задача не очень сложна: изменить 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 файл. подскажите плиз как сделать правильно.
 

alik86

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

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 586
272
#4
alik86 ДОМ не отобразит изменения, в потоке, без Serialize
 

alik86

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

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 586
272
#6
сам ДОМ - это обект в памяти, в нем нет стримов...

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

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

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

pbnoob

Well-known member
25.08.2006
135
0
#7
Для alik86
Да, так как мне текстовый отчет не нужен, то возможно я действительно пытался править InputStream

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

alik86

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

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

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 586
272
#10
как правильно использовать Serialize?
открыть пример, на котю я дал ссылку или искать в гугле
Serialize использовать в процедуре PostProcessing
вот до этого domParser.Process
надо зарегать On Event... (названия эвента нет под рукой) с именем процедуры, в кот. меняется ДОМ
после сериалайз - результат будет в output (в примере выше - стрим)
 

pbnoob

Well-known member
25.08.2006
135
0
#11
Спасибо все кто старался помочь. :lovecodeby:

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

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 586
272
#12
Если что, могу выложить код.
вы поступили (как бы сказать) не тем способом, как обычно решаются эти задачи, а потому ценность вашего кода - только для вас :rolleyes:
мало того что на ДОМ (построение) было сожрано время и память, дык еще повторно сканируется всё дерево
расточительное, по ресурсам, программирование врядли можно приветствовать
 

alik86

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

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 586
272
#14
А DOM, как не крути, - штука хорошая.
можно почитать в тырнете - область применения
люди не дураки раз придумывали SAX, XSLT...
ДОМ - большое потребление памяти, время на создание, необходимость внесения изменений на "языке программирования", + удобство работы на "языке программирования"
XSLT - всё как у ДОМ за иключ. языка программирования (он и есть XSL) т.е. пишем прогу и больше её не трогаем (всё остальное можно делать на XSL)
SAX - работа с потоком целиком, необходимость внесения изменений на "языке программирования", + минимальное потребление памяти

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

pbnoob

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

seoman2

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

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

garrick

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

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

seoman2

Lotus team
17.02.2010
465
1
#19
измененное дерево сохраняется
Смотрел пример, так и не понял ничего....
Вот я делаю в кнопке так:

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

Lotus team
17.02.2010
465
1
#20
NotesSAXParser мне не подойдет, теги в дереве могут повторятся. Да и так глянул, у NotesSAXParser есть только метод Output, значит он пишет в другой файл все узлы? А мне надо замена pyfxtybq, а не генерация по всем узлам нового xml.