Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / ParseStream / 21 сообщений из 21, страница 1 из 1
24.06.2011, 14:10
    #37323638
AndreiG
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
Добрый день!
Уважаемое сообщество подскажите пожалуйста.
Есть поток в котором храниться xml (кусок xml ниже)
<ID.33>
<ID.33.1.TypeMessage>APA</ID.33.1.TypeMessage>
</ID.33>
<PID>
<PID.5.FIO>
<PN.1.Surname>hjkhjkfhsdjkf</PN.1.Surname>
<PN.2.Name>hfghdfh</PN.2.Name>
<PN.3.Patronymic>hfghfghdf</PN.3.Patronymic>
<PID.7.BirthDay><TS>62251</TS></PID.7.BirthDay>
Как распарсить данный поток и получить значение "hjkhjkfhsdjkf" из элемента <PN.1.Surname>?
...
Рейтинг: 0 / 0
24.06.2011, 14:37
    #37323694
Блок А.Н.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
Создаете класс, наследованный от %XML.Adaptor, настраиваете поля (по умолчанию они будут отображаться с тегами как названия полей)

потом создаете объект класса %XML.Reader, открываете поток, и

d reader.Correlate("PID","MyClass")
d reader.Next(.reply,.sc)

У вас двухуровневая структура как минимум, и класс должен быть содержащим подклассы.
Как такие классы оформлять - посмотрите в тебе XML-Word, там обратная задача, из классов сгенерить нужный XML,
но разницы особой нет.

Еще можно через %XML.TextReader, но это гораздо сложнее, чем через отображение классов.
...
Рейтинг: 0 / 0
24.06.2011, 14:44
    #37323707
AndreiG
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
Здравствуйте!
Я этот поток передаю с клиента на сервер! Мне нужно распарсить и получить фамилию, потом эту фамилию использовать при запросе!
...
Рейтинг: 0 / 0
24.06.2011, 14:49
    #37323723
andrew_tsw
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
Можно сделать и без использования reader.Correlate("PID","MyClass")
Например, так:

set reader = ##class(%XML.Reader).%New()
do reader.OpenStream(stream)
#dim document as %XML.Document = reader.Document
#dim node as %XML.Node = document.GetDocumentElement()
и т.д.

а дальше последовательно просматривать структуру документа и искать то место, которое нужно.

Representing an XML Document as a DOM
...
Рейтинг: 0 / 0
24.06.2011, 16:00
    #37323926
AndreiG
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
а как получить значение эл-та <PN.2.Name>, если он в эл-те <PID.5.FIO>?
<PID.5.FIO>
<PN.1.Surname>hjkhjkfhsdjkf</PN.1.Surname>
<PN.2.Name>hfghdfh</PN.2.Name>
</PID.5.FIO>
...
Рейтинг: 0 / 0
24.06.2011, 16:32
    #37323999
Блок А.Н.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
А вы каким методом хотите?
Что уже попробовали сделать?
...
Рейтинг: 0 / 0
24.06.2011, 16:38
    #37324013
AndreiG
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
т.к. я на сервере делаю парсинг я пробую как предложил andrew_tsw. не получается взять значение элемента по названию тега
...
Рейтинг: 0 / 0
24.06.2011, 16:42
    #37324029
Блок А.Н.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
А его методом не по названию, а по порядку, если не ошибаюсь.
Причем там причуды в некоторых местах, так как элементом являются не только элементы, но и аттрибуты, контент и всякое такое.
Еще разбирать придется, в каком же месте и что мы прочитали.

Прямо рекомендую свой способ.
Может быть, он в первый раз кажется сложнее, но это тот случай, когда "лучше день потерять, потом за 5 минут долететь".
Получаете сразу готовые объекты классов с нужными полями.
...
Рейтинг: 0 / 0
24.06.2011, 16:48
    #37324040
Turk
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
AndreiG,
примерный код с помощью %XML.TextReader (без необходимости заведения дополнительных классов):
Код: plaintext
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.
s sc = ##class(%XML.TextReader).ParseFile(FileName,.reader)
q:($$$ISERR(sc)) $lb(0, "Ошибка разбора XML-файла: "_$SYSTEM.Status.GetErrorText(sc))
//
s res = $lb(0, "Элемент PN.3.Patronymic не найден")
s fExit = 0
while (reader.Read())
{
	continue:(reader.NodeType'="element")
	//
	if (reader.Name = "PID.5.FIO")
	{
		while (reader.Read())
		{
			q:(reader.Name="PID.5.FIO")&&(reader.NodeType="endelement")
			//
			if (reader.Name = "PN.3.Patronymic") && (reader.NodeType = "element")
			{
				s res = $lb(1,reader.Value)
				s fExit = 1
				q
			}
		}
		q:(fExit)
	}
}
//
k reader
q res
...
Рейтинг: 0 / 0
24.06.2011, 16:48
    #37324043
AndreiG
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
спс за подсказку! буду пробовать.
...
Рейтинг: 0 / 0
24.06.2011, 17:19
    #37324104
AndreiG
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
Turk, попробовал ваш пример. Результат получаю вот такой:
Мне такое не надо)
...
Рейтинг: 0 / 0
24.06.2011, 17:30
    #37324119
Блок А.Н.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
Метод Turk-работает, вы че-то наверно не так сделали.

Кстати, у вас в примере XML корявый, PID не закрывается
...
Рейтинг: 0 / 0
24.06.2011, 17:41
    #37324140
AndreiG
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
вот весь xml
<?xml version="1.0" encoding="Windows-1251"?>
<InfoPatient>
<MSH>
<MSH.1.FieldSeparator>|</MSH.1.FieldSeparator>
<MSH.2.EncodingCharacters>^~\</MSH.2.EncodingCharacters>
<MSH.3.SendingApplication>
<MSH.3.1.SendingApplicationName>HEALTHWEBPATIENT</MSH.3.1.SendingApplicationName>
<MSH.3.2.SendingNamespace>HEALTH</MSH.3.2.SendingNamespace>
</MSH.3.SendingApplication>
<MSH.4.SendingFacility>HOSPITAL</MSH.4.SendingFacility>
<MSH.5.HostApplication>
<MSH.5.1.HostApplicationName>MIS .... </MSH.5.1.HostApplicationName>
<MSH.5.2.HostNamespace>HEALTH</MSH.5.2.HostNamespace>
</MSH.5.HostApplication>
<MSH.6.HostFacility>HOSPITAL 123</MSH.6.HostFacility>
<MSH.7.DatatimeOfMessage>
<TS>
<TS.1>201108241326</TS.1>
</TS>
</MSH.7.DatatimeOfMessage>
</MSH>
<QRT>
<ST.25>201108241326</ST.25>
<ID.26>R</ID.26>
<CQ.31>RD</CQ.31>
<ID.33>
<ID.33.1.TypeMessage>APA</ID.33.1.TypeMessage>
</ID.33>
<PID>
<PID.5.FIO>
<PN.1.Surname>hjkhjkfhsdjkf</PN.1.Surname>
<PN.2.Name>hfghdfh</PN.2.Name>
<PN.3.Patronymic>hfghfghdf</PN.3.Patronymic>
<PID.7.BirthDay>
<TS>62251</TS>
</PID.7.BirthDay>
</PID.5.FIO>
<PID.11.Adress>
<AD.1/>
<AD.2/>
<AD.3/>
</PID.11.Adress>
</PID>
</QRT>
</InfoPatient>

а вот метод:
Method GetFile(ByRef pStream As %Library.BinaryStream) [ WebMethod ]
{

s sc = ##class(%XML.TextReader).ParseStream(pStream,.reader)

q:($$$ISERR(sc)) $lb(0, "Ошибка разбора XML-файла: "_$SYSTEM.Status.GetErrorText(sc))
//
s res = $lb(0, "Элемент PN.3.Patronymic не найден")

s fExit = 0

while (reader.Read())

{
continue:(reader.NodeType'="element")
//

if (reader.Name = "PID.5.FIO")
{
while (reader.Read())
{

q:(reader.Name="PID.5.FIO")&&(reader.NodeType="endelement")
//

if (reader.Name = "PN.1.Surname") && (reader.NodeType = "element")
{
s res = $lb(1,reader.Value)


Set file=##class(%Library.File).%New("C:\2.txt")
Set ok=file.Open("WN")
If 'ok Quit
Do file.Write(res)
Do file.Close()


s fExit = 1

q
}
}
q:(fExit)
}
}
//

k reader
q res


}
}
...
Рейтинг: 0 / 0
24.06.2011, 17:42
    #37324141
AndreiG
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
что не так?
...
Рейтинг: 0 / 0
24.06.2011, 17:52
    #37324162
Блок А.Н.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
Так лучше.
Секунду, нарисую пример.

Вам же по идее нужно парсить весь файл?
Вы же не радо одного поля это затеваете?
...
Рейтинг: 0 / 0
24.06.2011, 17:59
    #37324172
AndreiG
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
Мне надо из потока pStream, который приходит от WebClient и содержит различную информацию о человеке вытащить Фамилию и использовать ее в запросе
...
Рейтинг: 0 / 0
24.06.2011, 18:27
    #37324201
Блок А.Н.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
Хм, в моем методе бяка в том, что если мы цепляем из потока тег PID, то мы должны для него полное отображение классов нарисовать, а это бывает много.
Я решил поискать и распарсить PID, для того, чтобы распарсить InfoPatient классов надо наплодить больше.

Собственно, сам код:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
 s reader=##class(%XML.Reader).%New()
 d reader.OpenFile("e:\temp\1.xml")
 d reader.Correlate("PID","Reader.PID") 
 #dim obj as Reader.PID
 while reader.Next(.obj,.sc)
 	{w !,obj.FIO.Surname
 	}
 

Нужные классы:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
Class Reader.PID Extends (%Persistent, %XML.Adaptor)
{

Property FIO As FIO(XMLNAME = "PID.5.FIO");

Property Address As Address(XMLNAME = "PID.11.Adress");

}
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Class Reader.FIO Extends (%Persistent, %XML.Adaptor)
{

Property Surname As %String(XMLNAME = "PN.1.Surname");

Property Name As %String(XMLNAME = "PN.2.Name");

Property Patronymic As %String(XMLNAME = "PN.3.Patronymic");

Property Birtday As BirthDay(XMLNAME = "PID.7.BirthDay");

}
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Class Reader.Address Extends (%Persistent, %XML.Adaptor)
{

Property AD1 As Value(XMLNAME = "AD.1");

Property AD2 As Value(XMLNAME = "AD.2");

Property AD3 As Value(XMLNAME = "AD.3");

}
Код: plaintext
1.
2.
3.
4.
5.
6.
Class Reader.Value Extends (%Persistent, %XML.Adaptor)
{

Property Value As %String(XMLPROJECTION = "CONTENT");

}
...
Рейтинг: 0 / 0
25.06.2011, 07:04
    #37324536
Блок А.Н.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
Че-то чую, не все классы выложил :)
Код: plaintext
1.
2.
3.
4.
5.
Class Reader.BirthDay Extends (%Persistent, %XML.Adaptor)
{

Property TS As Reader.Value(XMLNAME = "TS");

}
...
Рейтинг: 0 / 0
25.06.2011, 11:33
    #37324617
AndreiG
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
Спасибо всем за подсказки! Проблему решили так:
Method GetFile(ByRef pStream As %Library.BinaryStream) [ WebMethod ]
{
Set cls=##CLASS(%XML.TextReader).ParseStream(pStream,.reader)
Set stream=##class(%GlobalCharacterStream).%New()
k ^testXML
While reader.Read()
{
If (reader.NodeType = "element")
{
s nam=reader.Name
if (nam="PN.1.Surname")||( nam="PN.2.Name")||(nam="PN.3.Patronymic")
{
while reader.Read()
{
q:(reader.Name=nam)&&(reader.NodeType="endelement")
s val=reader.Value
s testXML(nam)=val

q
}
}

}

}

s ^testXML("FIO")=testXML("PN.1.Surname")_testXML("PN.2.Name")_testXML("PN.3.Patronymic")


}
...
Рейтинг: 0 / 0
27.06.2011, 08:06
    #37325458
Turk
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
AndreiGTurk, попробовал ваш пример. Результат получаю вот такой:
Мне такое не надо)
В моем примере возвращается не строка, а список ($listbuild), где 1й элемент - результат операции (0 - ошибка, 1 - успешно), а 2й - строка со значением тэга (если успешно) или текст ошибки.
...
Рейтинг: 0 / 0
27.06.2011, 09:33
    #37325509
krvsa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ParseStream
AndreiGвот весь xml
Код: plaintext
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.
<?xml version="1.0" encoding="Windows-1251"?>
<InfoPatient>
  <MSH>
    <MSH. 1 .FieldSeparator>|</MSH. 1 .FieldSeparator>
    <MSH. 2 .EncodingCharacters>^~\</MSH. 2 .EncodingCharacters>
    <MSH. 3 .SendingApplication>
      <MSH. 3 . 1 .SendingApplicationName>HEALTHWEBPATIENT</MSH. 3 . 1 .SendingApplicationName>
      <MSH. 3 . 2 .SendingNamespace>HEALTH</MSH. 3 . 2 .SendingNamespace>
    </MSH. 3 .SendingApplication>
    <MSH. 4 .SendingFacility>HOSPITAL</MSH. 4 .SendingFacility>
    <MSH. 5 .HostApplication>
      <MSH. 5 . 1 .HostApplicationName>MIS .... </MSH. 5 . 1 .HostApplicationName>
      <MSH. 5 . 2 .HostNamespace>HEALTH</MSH. 5 . 2 .HostNamespace>
    </MSH. 5 .HostApplication>
    <MSH. 6 .HostFacility>HOSPITAL  123 </MSH. 6 .HostFacility>
    <MSH. 7 .DatatimeOfMessage>
      <TS>
        <TS. 1 > 201108241326 </TS. 1 >
      </TS>
    </MSH. 7 .DatatimeOfMessage>
  </MSH>
  <QRT>
    <ST. 25 > 201108241326 </ST. 25 >
    <ID. 26 >R</ID. 26 >
    <CQ. 31 >RD</CQ. 31 >
    <ID. 33 >
      <ID. 33 . 1 .TypeMessage>APA</ID. 33 . 1 .TypeMessage>
    </ID. 33 >
    <PID>
      <PID. 5 .FIO>
        <PN. 1 .Surname>hjkhjkfhsdjkf</PN. 1 .Surname>
        <PN. 2 .Name>hfghdfh</PN. 2 .Name>
        <PN. 3 .Patronymic>hfghfghdf</PN. 3 .Patronymic>
        <PID. 7 .BirthDay>
          <TS> 62251 </TS>
        </PID. 7 .BirthDay>
      </PID. 5 .FIO>
      <PID. 11 .Adress>
        <AD. 1 />
        <AD. 2 />
        <AD. 3 />
      </PID. 11 .Adress>
    </PID>
  </QRT>
</InfoPatient>

Если это и весь текст - загнать его в строчку, а далее

Код: plaintext
w $p($p(str,"<PN.1.Surname>", 2 ),"</PN.1.Surname>")
...
Рейтинг: 0 / 0
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / ParseStream / 21 сообщений из 21, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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