powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Xml.Adaptor класс импорт <=> экспорт
3 сообщений из 3, страница 1 из 1
Xml.Adaptor класс импорт <=> экспорт
    #38303177
sigmov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Суть вопроса в том как импортировать данные из Xml в существующий объект

У меня есть класс, он передается с сервера на клиент в виде Xml, затем на клиенте Xml может быть модифицирован и в окончании цикла передается обратно на сервер, где он должен быть загружен в объект из которого был сформирован изначально.

Однако я не могу загрузить Xml в уже существующий объект

У меня есть класс
Class Test.XmlSupporter Extends (%Persistent, %XML.Adaptor)
{

Property A As %String [ InitialExpression = "GGG" ];

Property B As %String [ InitialExpression = "HHH" ];

/// Экспортируем класс в Xml
ClassMethod TestExportInstanceToXml()
{
  #Dim obj As XmlSupporter = ##class(XmlSupporter).%New()
  #Dim xmlView As %String = ""
  #Dim status As %Status = obj.XMLExportToString(.xmlView)
  if (status = $$$OK){
    Write "XmlView = ",xmlView,!
  }
  /// Это работает как надо (!!!) - объект экспортировался
  /// XmlView = <XmlSupporter><A>GGG</A><B>HHH</B></XmlSupporter>
}

/// Создаем новый объект из Xml
/// (!) Согласно BestPractice InterSystems
ClassMethod TestImportNewInstanceFromXml()
{
  #Dim obj As XmlSupporter = $$$NULLOREF
  #Dim xmlReader As %XML.Reader = ##class(%XML.Reader).%New()
  #Dim status As %Status = xmlReader.OpenString("<XmlSupporter><A>CCC</A><B>DDD</B></XmlSupporter>")
  if (status = $$$OK){
    Do xmlReader.Correlate("XmlSupporter","Test.XmlSupporter")
    if (xmlReader.Next(.obj,.status)){
      if (status = $$$OK){
        // Объект успешно создан
        Write obj," A = ",obj.A," B = ",obj.B,!
      }
    }
  } 
  /// Это работает как надо (!!!) - объект импортирован и создан
  /// 3@Test.XmlSupporter A = CCC B = DDD
}

/// Экспортируем объект в Xml, изменяем его Xml, пытаемся загрузить изменения обратно в объект
ClassMethod TestSyncronizeObjectAndXml()
{
  #Dim obj As XmlSupporter = ##class(XmlSupporter).%New()
  #Dim xmlView As %String = ""
  #Dim status As %Status = obj.XMLExportToString(.xmlView)
  if (status = $$$OK){
    Set xmlView = $Replace(xmlView,"HHH","KKK") // изменяем один из атрибутов
    Write "XmlView = ",xmlView,!
    #Dim xmlReader As %XML.Reader = ##class(%XML.Reader).%New()
    set status = xmlReader.OpenString(xmlView)
    if (status = $$$OK){
      Set status = obj.XMLImport("XmlSupporter",,,xmlReader.Document) // Вот тут мы спотыкаемся
      if (status = $$$OK){
        Write obj,!," B = ",obj.B,!
      } else {
        Do $system.Status.DisplayError(%objlasterror)
      }
    }
  }
  // А вот тут ТРАБЛА
  // XmlView = <XmlSupporter><A>GGG</A><B>HHH</B></XmlSupporter>
  // ОШИБКА #5002: Ошибка: <UNDEFINED>zXMLImport+4^%XML.Adaptor.1 *node
}
}
Кстати такая фишка - InterSystems не рекомендует вызывать XMLImport напрямую, но альтернативы никакой другой я не нашел.

Кто можеть помочь? - буду весьма признателен
...
Рейтинг: 0 / 0
Xml.Adaptor класс импорт <=> экспорт
    #38303336
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sigmovКстати такая фишка - InterSystems не рекомендует вызывать XMLImport напрямуюПравильно, методы [Internal] лучше не использовать самим.
sigmovно альтернативы никакой другой я не нашел.А пример с Correlate() разве не подходит?Class Test.XmlSupporter Extends (%RegisteredObject, %XML.Adaptor)
{

Property A As %String [ InitialExpression = "GGG" ];

Property B As %String [ InitialExpression = "HHH" ];

/// Экспортируем класс в Xml
ClassMethod TestExportInstanceToXml()
{
  
  Set obj = ##class(XmlSupporter).%New()
  Set xmlView = ""
  if $$$ISOK(obj.XMLExportToString(.xmlView))
  {
    Write "XmlView = ",xmlView,!
  }
  /*
  Это работает как надо (!!!) - объект экспортировался
  XmlView = <XmlSupporter><A>GGG</A><B>HHH</B></XmlSupporter>
  */
}

/// Создаем новый объект из Xml
/// (!) Согласно BestPractice InterSystems
ClassMethod TestImportNewInstanceFromXml()
{

  #Dim obj As XmlSupporter = $$$NULLOREF
  Set xmlReader = ##class(%XML.Reader).%New()
  if $$$ISOK(xmlReader.OpenString("<XmlSupporter><A>CCC</A><B>DDD</B></XmlSupporter>"))
  {
    Do xmlReader.Correlate("XmlSupporter",$classname())
    if (xmlReader.Next(.obj,.status)){
      if $$$ISOK(status)
      {
        // Объект успешно создан
        Do $system.OBJ.Dump(obj)
      }
    }
  } 
  /*
  Это работает как надо (!!!) - объект импортирован и создан
  +----------------- general information ---------------
  |      oref value: 3
  |      class name: Test.XmlSupporter
  | reference count: 1
  +----------------- attribute values ------------------
  |                  A = "CCC"
  |                  B = "DDD"
  */
}

/// Экспортируем объект в Xml, изменяем его Xml, пытаемся загрузить изменения обратно в объект
ClassMethod TestSyncronizeObjectAndXml()
{
  
  Set xmlView = ""
  Set obj = ##class(XmlSupporter).%New()
  if $$$ISOK(obj.XMLExportToString(.xmlView)){
    Write "(До) XmlView = ",xmlView,!
    Set xmlView = $Replace(xmlView,"HHH","KKK") // изменяем один из атрибутов
    Write "(После) XmlView = ",xmlView,!
    Set xmlReader = ##class(%XML.Reader).%New()
    if $$$ISOK(xmlReader.OpenString(xmlView))
    {
      Write !!,"---- До ----",!!
      Do $system.OBJ.Dump(obj)
      Do xmlReader.Correlate("XmlSupporter",$classname())
      if (xmlReader.Next(.obj,.status)) // Вот тут мы не спотыкаемся
      { 
        if $$$ISOK(status)
        {
          Write !!,"---- После ----",!!
          Do $system.OBJ.Dump(obj)
        } else {
          Do $system.Status.DisplayError(%objlasterror)
        }
      }
    }
  }

  ;А вот тут нет ТРАБЛ
}

}
...
Рейтинг: 0 / 0
Xml.Adaptor класс импорт <=> экспорт
    #38303709
sigmov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
servit , спасибо за ответ
А пример с Correlate() разве не подходит?
Дело в том что в примере с Correlate он не загружает Xml в переданный методу объект, а банально присваивает ссылке новый объект и уже в него загружает Xml (т.е. это уже не тот объект который нужно синхронизировать)

Нашел какое-никакое решение, унаследовав %XmlReader и изъяв из метода Next все лишнее (пересоздание объекта)
Вроде даже работает. Код:
Common.Xml.XmlObjectReader
Код: python
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
/// Загрузчик XmlString To Object
Class Common.Xml.XmlObjectReader Extends %XML.Reader [ Abstract ]
{
/// Get and return the next object.<p>
/// <method>Next</method> returns 1 (true), if the next object matching one of the Correlate criteria 
/// is found and successfully imported.<br>
/// <method>Next</method> returns 0 (false) and a %Status of $$$OK in sc
/// after all objects have been imported.<br>
/// <method>Next</method> returns 0 (false) and an error %Status in sc, 
/// if an error has occurred importing this object.<p>
/// The <var>namespace</var> argument indicates the default namespace 
/// for this XML file.
Method LoadToObject(ByRef oref As %ObjectHandle, ByRef sc As %Status, namespace As %String = "") As %Integer
{
 Set sc=$$$OK
 If i%Document="" Quit 0
 If i%Node="" Quit 0
 Set tree = i%Document.DocumentId
 Set found = 0
 While i%ParentNodeId '= "" {
	If '..NodeIsCurrent {
		If $$$xmlaIsTop(tree,i%ParentNodeId) Quit
		Set pcl=i%ParentChildlist
		$$$xmlaNextChild(tree,i%ParentNodeId,pcl,i%Node,descriptor)
		Set i%ParentChildlist=pcl
		Set i%Descriptor=descriptor
	}
	While i%Node '= "" {
		Set ..NodeIsCurrent=0
		If $$$xmlaGetNodeType(tree,i%Descriptor)=$$$xmlELEMENTNODE {
			$$$xmlaGetChildListFromDescriptor(tree,i%Descriptor,i%Childlist)
			Set element = $$$xmlaGetLocalName(tree,i%Childlist)
			Set type = $get(i%CorrelationTable($c(0)))
			If type = "" Set type = ..ResolveElement(element,namespace)
			If type '= "" {
				If oref'="" {
					Merge idlist=i%Idlist
					$$$XMLTimerNewMark
					Set sc=oref.XMLImport(element,i%OpenFormat,namespace,i%Document,i%Node,.idlist)
					$$$XMLTimerRecord("XMLImport")
					Merge i%Idlist=idlist
				}
				Set found = 1
				Quit
			}
			If $$$xmlaHasChildNodes(tree,i%Childlist) {
				Set i%ParentNodeId = i%Node
				Set i%ParentChildlist = i%Childlist
				Set i%Node = ""
			}
		}
		If $$$xmlaIsTop(tree,i%ParentNodeId) Quit
		Set pcl=i%ParentChildlist
		If i%Node="" {
			$$$xmlaFirstChild(tree,i%ParentNodeId,pcl,i%Node,descriptor)
		} Else {
			$$$xmlaNextChild(tree,i%ParentNodeId,pcl,i%Node,descriptor)
		}
		Set i%ParentChildlist=pcl
		Set i%Descriptor=descriptor
	}
	If found Quit
	Set i%Node = i%ParentNodeId
	Set i%Childlist=i%ParentChildlist
	Set i%Descriptor=i%ParentDescriptor
	Set i%ParentNodeId = $$$xmlaParentNode(tree,i%Node)
	If $$$xmlaIsTop(tree,i%ParentNodeId) {
		Set i%ParentNodeId=""
	} Else {
		$$$xmlaGetChildList(tree,i%ParentNodeId,i%ParentChildlist,i%ParentDescriptor)
	}
 }
 If $$$ISOK(sc) && found Quit 1
 Set i%Node = ""
 Quit 0
}

}

...
Рейтинг: 0 / 0
3 сообщений из 3, страница 1 из 1
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Xml.Adaptor класс импорт <=> экспорт
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]