Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: ActiveX/СОМ/CORBA > Получение строки из XML


Автор: aktuba 17.8.2007, 09:10
Вот пример XML:
Код

<?xml version="1.0" encoding="Windows-1251"?>
<methodResponse>
  <fault>
    <value>
      <struct>
        <member>
          <name>faultCode</name>
          <value><int>-32601</int></value>
        </member>
        <member>
          <name>faultString</name>
          <value><string>Ошибка на сервере. Запрошенный метод <em>blogger.getUserInfo1</em> не определен.</string></value>
        </member>
      </struct>
    </value>
  </fault>
</methodResponse>


Вот код:
Код

const
  C_TypeString = 'string';
  C_Name = 'name';
  C_Value = 'value';
  C_Struct = 'struct';
  C_Int = 'int';
  C_I4 = 'i4';

var
  lXML: IXMLDocument;
  lNode, lMember, lName, lValue, lType: IXMLNode;
  lUser: TUserData;
  lCode: Integer;
  lErrCode: Integer;
  lErrText: WideString;
  Idx, Idx2: Integer;
  lNameValue, lTypeName: string;
begin
  lXML := NewXMLDocument;
  lXML.XML.Text := AXML;
  lXML.Active := True;
  lXML.Encoding := 'Windows-1251';
  try
    lNode := lXML.DocumentElement.ChildNodes.First;
    lCode := 0;
    if lNode.NodeName = 'fault' then lCode := 1; // Ошибка запроса
    if lNode.NodeName = 'params' then lCode := 2; // Запрос выполнен успешно
    case lCode of
      1: // Ошибка запроса
        begin
          lErrCode := -1;
          lErrText := C_NotDefinedError;
          while Assigned(lNode) and (lNode.NodeName <> C_Struct) do
            lNode := lNode.ChildNodes.First;
          if Assigned(lNode) then
            begin
              for Idx := 0 to lNode.ChildNodes.Count - 1 do
                begin
                  lMember := lNode.ChildNodes[Idx];
                  lName := lMember.ChildNodes.FindNode(C_Name);
                  lNameValue := '';
                  if Assigned(lName) then
                    lNameValue := AnsiLowerCase(string(lName.NodeValue));
                  lValue := lMember.ChildNodes.FindNode(C_Value);
                  lType := lValue.ChildNodes.First;
                  lTypeName := '';
                  if Assigned(lType) then
                    lTypeName := AnsiLowerCase(lType.NodeName);
                  if lNameValue = 'faultcode' then
                    if (lTypeName = C_Int) or (lTypeName = C_I4) then
                      lErrCode := StrToIntDef(string(lType.NodeValue), -1);
                  if lNameValue = 'faultstring' then
                    if lTypeName = C_TypeString then
                      lErrText := lType.NodeValue;
                end;  
            end;
        end;
      2: // Запрос выполнен успешно
        begin
        ...
        end;
    end;
  finally
    lXML.Active := False;
  end;
end;


Никак не могу получить строку
Код

Ошибка на сервере. Запрошенный метод <em>blogger.getUserInfo1</em> не определен.


Направьте на путь истинный...  smile  smile 

Автор: aktuba 17.8.2007, 09:46
Попробовал сделать следующее: убрал теги между <string> и </string>. Теперь XML у меня выглядит так:
Код

<methodResponse>
  <fault>
    <value>
      <struct>
        <member>
          <name>faultCode</name>
          <value><int>-32601</int></value>
        </member>
        <member>
          <name>faultString</name>
          <value><string>Ошибка на сервере. Запрошенный метод blogger.getUserInfo1 не определен.</string></value>
        </member>
      </struct>
    </value>
  </fault>
</methodResponse>


Однако это не помогло  smile 

Автор: MetalFan 17.8.2007, 13:09
дай пример приложения и xml'ку в архиве) поковыряемса

Автор: aktuba 17.8.2007, 15:40
не могу =(((( получаю из сети. но то, что я привет - это один в один. сюда скопи-пастил...

Автор: EvilsInterrupt 17.8.2007, 15:49
Вот пример передачи и принятия XML-документации на основе TjanXMLParser2.

Если у тебя документ XML валиден, то думаю тебе мой пример поможет!

Совет:
Проверить кодировку, одно дело она в заголовке, другое дело соответствует ли?

Автор: aktuba 17.8.2007, 15:59
EvilsInterrupt, конечно! Иначе галочка стояла-бы...

Автор: EvilsInterrupt 17.8.2007, 16:42
Да блин, пост подредактировал и все, чел не видит что я ему помощь кинул ))). Хотелось бы чтобы на форумах не только колнку даты добавления нового поста, но и время последнего апдейта была - иногда это очень нужно!

Автор: aktuba 17.8.2007, 16:54
Цитата

Если у тебя документ XML валиден, то думаю тебе мой пример поможет!


XML валиден, проверял. Любой редактор, IE, FF открывают без проблем.

Цитата

Проверить кодировку, одно дело она в заголовке, другое дело соответствует ли?


Соответствует, т.к. перед тем как перевести строку в XML, преобразую ее в нужный вид.

Автор: aktuba 17.8.2007, 17:25
Так, проблема решена. Трабла была в следующем (взято из XMLDoc):
Код

procedure TXMLNode.CheckTextNode;
begin
  { Create the actual text node when none already exists }
  if not DOMNode.hasChildNodes then
  begin
    DOMNode.appendChild(DOMNode.ownerDocument.createTextNode(''));
    SetChildNodes(nil);
  end
  else if (DOMNode.childNodes.length > 1) or
    not (DOMNode.childNodes[0].nodeType in [TEXT_NODE, CDATA_SECTION_NODE]) then
    XMLDocError(SNotSingleTextNode, [DOMNode.nodeName]);
end;


т.е., проверяется узел на наличие чилдов и если наличие обнаружено, то XMLDoc считает, что данный нод не может содержать текстовое значение. Т.к. изначально в строке есть html-теги, то они воспринимаются за child-ы... Решение пока следующее - все < и > в ноде <string> заменяю на [ и ] соответственно. Вот код, может кто что предложит...
Код

const
  C_String = '<string>';
  C_UnString = '</string>';
var
  lPos: Integer;
  f: Boolean;
begin
  lPos := 1;
  f := False;
  FResponse := Utf8ToAnsi(FResponse);
  while lPos <= Length(FResponse) do
    begin
      if Copy(FResponse, lPos, Length(C_String)) = C_String then
        begin
          f := True;
          Inc(lPos, Length(C_String));
          Continue;
        end;
      if Copy(FResponse, lPos, Length(C_UnString)) = C_UnString then
        begin
          f := False;
          Inc(lPos, Length(C_UnString));
          Continue;
        end;
      if (FResponse[lPos] = '<') and f then
        FResponse[lPos] := '[';
      if (FResponse[lPos] = '>') and f then
        FResponse[lPos] := ']';
      Inc(lPos);
    end;
  FProc(AnsiToUtf8(FResponse));
end;

Автор: EvilsInterrupt 17.8.2007, 17:47
aktuba, 
Еще, есть у тебя в XML такие строки:
Код

        <member>
          <name>faultCode</name>
          <value><int>-32601</int></value>
        </member>

не рекомендую!!!

Лучше:
Код

        <member>
          <name>faultCode</name>
          [U]<value type="int">-32601</value>[/U]
        </member>


Автор: aktuba 17.8.2007, 18:07
Цитата

Еще, есть у тебя в XML такие строки
...
не рекомендую!!!


Да я даже не могу ничего поменять - это xml-rpc. Это стандарт и ничего с этим не сделаешь =(...

Автор: EvilsInterrupt 17.8.2007, 19:16
aktuba, Уж не OPC-XMLDA ковыряешь? ))

Автор: aktuba 17.8.2007, 20:18
Цитата

aktuba, Уж не OPC-XMLDA ковыряешь? )) 


Нет, blogger

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)