【问题标题】:How to check XML file if node exists and retrieve value in Progress4GL如果节点存在,如何检查 XML 文件并在 Progress4GL 中检索值
【发布时间】:2020-09-23 14:57:45
【问题描述】:

Progress4GL 开发人员您好,

在对 UPS 进行成功的 SOAP 调用后,我将以下 XML 响应存储在名为 cBody 的 longchar 变量中:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<trk:TrackResponse xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:trk="http://www.ups.com/XMLSchema/XOLTWS/Track/v2.0">
  <common:Response xmlns:common="http://www.ups.com/XMLSchema/XOLTWS/Common/v1.0">
    <common:ResponseStatus>
      <common:Code>1</common:Code>
      <common:Description>Success</common:Description>
    </common:ResponseStatus>
    <common:TransactionReference/>
  </common:Response>
  <trk:Shipment>
    <trk:InquiryNumber>
      <trk:Code>01</trk:Code>
      <trk:Description>ShipmentIdentificationNumber</trk:Description> 
      <trk:Value>MYTRACKERNUMBER</trk:Value>
    </trk:InquiryNumber>
 ...

我现在使用以下代码行将其存储为 X-DOCUMENT:

hDoc:LOAD("longchar",cBody2,FALSE).

现在我想检查我的回复是否有跟踪号,如果有,我想将跟踪号存储为变量。看来这是可能的: https://documentation.progress.com/output/ua/OpenEdge_latest/index.html#page/dvxml/examples-of-reading-an-input-xml-file.html

但是,这是我到目前为止所拥有的,而且它似乎不起作用。什么都没有输出,但没有运行时错误:

....
hDoc:LOAD("longchar",cBody,FALSE).

DEFINE variable hNodeRef as HANDLE NO-UNDO.
CREATE X-NODEREF hNodeRef.

hDoc:GET-DOCUMENT-ELEMENT(hNodeRef).
IF hNodeRef:NAME = "trk:value" THEN
message hNoderef:GET-ATTRIBUTE("id") hNoderef:ATTRIBUTE-NAMES.
....

【问题讨论】:

    标签: xml openedge progress-4gl


    【解决方案1】:

    您需要沿着树向下走才能到达您想要的节点。像下面这样的工作。这很费力,你需要自己清理(就像在 finally 块中一样)。

    define variable hXmlDoc as handle no-undo.
    define variable hXmlNode as handle no-undo.
    define variable hXmlNode2 as handle no-undo.
    define variable hXmlNode3 as handle no-undo.
    define variable loop as integer no-undo.
    define variable cnt as integer no-undo.
    
    create x-document hXmlDoc.
    hXmlDoc:load('file', 'soap.xml', no).
    
    create x-noderef hXmlNode.
    create x-noderef hXmlNode2.
    create x-noderef hXmlNode3.
    
    hXmlDoc:get-document-element(hXmlNode).
    
    cnt = hXmlNode:num-children.
    do loop = 1 to cnt:
        hXmlNode:get-child(hXmlNode2, loop).
        if hXmlNode2:name eq 'trk:Shipment' then
            leave.
    end.     
    
    cnt = hXmlNode2:num-children.
    do loop = 1 to cnt:
        hXmlNode2:get-child(hXmlNode3, loop).
        if hXmlNode3:name eq 'trk:InquiryNumber' then
            leave.
    end.
    
    // should be trk:InquiryNumber
    cnt = hXmlNode3:num-children.
    do loop = 1 to cnt:
        hXmlNode3:get-child(hXmlNode, loop).
        if hXmlNode:name eq 'trk:Value' then
            leave.
    end.
    
    // should be trk:Value
    hXmlNode:get-child(hXmlNode2, 1).
    
    message 
    hXmlNode:name skip
    hXmlNode2:node-value
    view-as alert-box.
    finally:
        delete object hXmlNode.
        delete object hXmlNode2.
        delete object hXmlNode3.
        delete object hXmlDoc.    
    end finally.
    

    【讨论】:

    • 感谢@nwahmaet,这对于理解如何使用 x-noderef 句柄来获取我需要的 XML 文件非常有帮助。 :)
    【解决方案2】:

    虽然 Peter 的回答没有错,但使用自动 XML 到 DataSet 映射的强大功能会简单得多。在这种情况下,您甚至不需要将数据集静态建模为 XML,ABL 会自动为您完成:

    def var lcresponse as longchar initial '<?xml version="1.0" encoding="ISO-8859-1" ?>
    <trk:TrackResponse xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:trk="http://www.ups.com/XMLSchema/XOLTWS/Track/v2.0">
      <common:Response xmlns:common="http://www.ups.com/XMLSchema/XOLTWS/Common/v1.0">
        <common:ResponseStatus>
          <common:Code>1</common:Code>
          <common:Description>Success</common:Description>
        </common:ResponseStatus>
        <common:TransactionReference/>
      </common:Response>
      <trk:Shipment>
        <trk:InquiryNumber>
          <trk:Code>01</trk:Code>
          <trk:Description>ShipmentIdentificationNumber</trk:Description> 
          <trk:Value>MYTRACKERNUMBER</trk:Value>
        </trk:InquiryNumber>
      </trk:Shipment>
    </trk:TrackResponse>'.
    
    def var hds as handle no-undo.
    def var hb  as handle no-undo.
    
    create dataset hds.
    hds:read-xml( "longchar", lcresponse, ?, ?, ? ).
    hb = hds:get-buffer-handle("InquiryNumber").
    hb:find-unique() no-error.
    if hb:available then 
       message hb:buffer-field("Value"):buffer-value.
    

    https://abldojo.services.progress.com:443/#/?shareId=5ed946344b1a0f40c34b8c5a

    【讨论】:

    • 谢谢 Stefan,我想知道这是怎么可能的,因为数据位于一个名为“value”的节点中,这是一个静态临时表字段的关键字,但这是解决方案并且工作得很好!再次感谢!
    • 是的,保留关键字可能会令人讨厌,在这种情况下,它会阻止 :: 快捷形式(消息 hb::Value)。对于静态临时表,您通常可以通过使用 serialize-name 来解决这个问题(例如:field myvalue serialize-name "value")。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-04
    相关资源
    最近更新 更多