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

Тема в разделе "Lotus - Программирование", создана пользователем pbnoob, 19 ноя 2010.

  1. pbnoob

    pbnoob Well-Known Member

    Регистрация:
    25 авг 2006
    Сообщения:
    135
    Симпатии:
    0
    Доброго дня!

    задача не очень сложна: изменить 1значение в XML файле. код на 90% взял из хэлпа, так как это мой первый опыт работы с XML.
    Код (Text):
    (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 файл. подскажите плиз как сделать правильно.
     
  2. lmike

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.081
    Симпатии:
    300
  3. alik86

    alik86 Lotus team
    Lotus team

    Регистрация:
    20 ноя 2008
    Сообщения:
    465
    Симпатии:
    0
    Noob, в Вашем примере на выходе получается текстовый файл-отчет (вроде как - я поленился изучить его полностью и глянул лишь между строк). А Вы хотите, как я понимаю, поменять файл который подаете на вход, причем изменения пытаетесь внести именно в InputStream (насколько я знаю, в Stream можно делать WriteText, но там нет ничего типа ReplaceText). Если Вы задумали использовать дхловсий парсинг, то и результат пишите в OutputStream и ищите его там (т.е. на выходе, а не на входе).
     
  4. lmike

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.081
    Симпатии:
    300
    alik86 ДОМ не отобразит изменения, в потоке, без Serialize
     
  5. alik86

    alik86 Lotus team
    Lotus team

    Регистрация:
    20 ноя 2008
    Сообщения:
    465
    Симпатии:
    0
    lmike, ну это уже следующий вопрос. Человек-то, по-моему, пытается вносить и искать изменения в intput`е.
     
  6. lmike

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.081
    Симпатии:
    300
    сам ДОМ - это обект в памяти, в нем нет стримов...

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

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

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

    pbnoob Well-Known Member

    Регистрация:
    25 авг 2006
    Сообщения:
    135
    Симпатии:
    0
    Для alik86
    Да, так как мне текстовый отчет не нужен, то возможно я действительно пытался править InputStream

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

    nvyush Lotus team
    Lotus team

    Регистрация:
    22 апр 2009
    Сообщения:
    2.317
    Симпатии:
    0
    Для этого лучше использовать класс NotesXSLTransformer
     
  9. alik86

    alik86 Lotus team
    Lotus team

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

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

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.081
    Симпатии:
    300
    открыть пример, на котю я дал ссылку или искать в гугле
    Serialize использовать в процедуре PostProcessing
    вот до этого domParser.Process
    надо зарегать On Event... (названия эвента нет под рукой) с именем процедуры, в кот. меняется ДОМ
    после сериалайз - результат будет в output (в примере выше - стрим)
     
  11. pbnoob

    pbnoob Well-Known Member

    Регистрация:
    25 авг 2006
    Сообщения:
    135
    Симпатии:
    0
    Спасибо все кто старался помочь. :lovecodeby:

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

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.081
    Симпатии:
    300
    вы поступили (как бы сказать) не тем способом, как обычно решаются эти задачи, а потому ценность вашего кода - только для вас :rolleyes:
    мало того что на ДОМ (построение) было сожрано время и память, дык еще повторно сканируется всё дерево
    расточительное, по ресурсам, программирование врядли можно приветствовать
     
  13. alik86

    alik86 Lotus team
    Lotus team

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

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.081
    Симпатии:
    300
    можно почитать в тырнете - область применения
    люди не дураки раз придумывали SAX, XSLT...
    ДОМ - большое потребление памяти, время на создание, необходимость внесения изменений на "языке программирования", + удобство работы на "языке программирования"
    XSLT - всё как у ДОМ за иключ. языка программирования (он и есть XSL) т.е. пишем прогу и больше её не трогаем (всё остальное можно делать на XSL)
    SAX - работа с потоком целиком, необходимость внесения изменений на "языке программирования", + минимальное потребление памяти

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

    pbnoob Well-Known Member

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

    seoman2 Lotus team
    Lotus team

    Регистрация:
    17 фев 2010
    Сообщения:
    435
    Симпатии:
    0
    Аналогичная задача - заполнить в входную XML-ку в нужные мне теги значения с полей дока.
    strm - в потоке XML-ка для редактирования.
    Set domParser=session.CreateDOMParser(strm, outputStream)
    Пока кроме как в outputStream записать через дерево dom все элементы, узлы и атрибуты, заменяя иногда нужные - не вижу (( тему перечитал.

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

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.081
    Симпатии:
    300
  18. garrick

    garrick Lotus team
    Lotus team

    Регистрация:
    26 окт 2009
    Сообщения:
    773
    Симпатии:
    52
    Ну, сказали же SAX или XLST. Ну, почему же опять DOM?
     
  19. seoman2

    seoman2 Lotus team
    Lotus team

    Регистрация:
    17 фев 2010
    Сообщения:
    435
    Симпатии:
    0
    Смотрел пример, так и не понял ничего....
    Вот я делаю в кнопке так:

    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".
     
  20. seoman2

    seoman2 Lotus team
    Lotus team

    Регистрация:
    17 фев 2010
    Сообщения:
    435
    Симпатии:
    0
    NotesSAXParser мне не подойдет, теги в дереве могут повторятся. Да и так глянул, у NotesSAXParser есть только метод Output, значит он пишет в другой файл все узлы? А мне надо замена pyfxtybq, а не генерация по всем узлам нового xml.
     
Загрузка...

Поделиться этой страницей