如何在 Inno Setup 中根据其子标签的值 select XML 标签

How to select XML tag based on value of its child tag in Inno Setup

我正在尝试在 XML 元素的子元素中搜索文本 "LIBRA ESTERLINA" 并检索其他子元素的值。但是我的查询没有结果。

我的代码基于 from and response from XPath: How to select elements based on their value?

function LoadValuesFromXMLMoneda(FileName: string): Boolean;
var
  XMLNode: Variant;
  XMLNodeList: Variant;
  XMLDocument: Variant;  
  Index: Integer;
  id, moneda, dollar, abr, singPlur, caracter : String;
begin
  XMLDocument := CreateOleObject('Msxml2.DOMDocument.6.0');
  try
    XMLDocument.async := False;
    XMLDocument.load(FileName);
    if (XMLDocument.parseError.errorCode <> 0) then
    begin
      Log('The XML file could not be parsed. ' + XMLDocument.parseError.reason);
      Result := False;
    end
      else
    begin
      XMLDocument.setProperty('SelectionLanguage', 'XPath');
      XMLNodeList :=
        XMLDocument.SelectNodes('//listaMonedas/item/moneda[text()="LIBRA ESTERLINA"]');
     for Index := 0 to XMLNodeList.length - 1 do
      begin
        XMLNode := XMLNodeList.item[Index];

        id       :=  XMLNode.SelectSingleNode('id').Text;
        moneda   :=  XMLNode.SelectSingleNode('moneda').Text;
        dollar   :=  XMLNode.SelectSingleNode('dollar').Text;
        abr      :=  XMLNode.SelectSingleNode('abr').Text;
        singPlur :=  XMLNode.SelectSingleNode('singPlur').Text;
        caracter :=  XMLNode.SelectSingleNode('caracter').Text;
        MsgBox(id+moneda+dollar+abr+singPlur+caracter,mbInformation,MB_OK); 
      end;
      Result := True;
    end;
  except
    Log('An error occured!' + #13#10 + GetExceptionMessage);
    Result := False;
  end;
end;

这里是XML:

<ns1:obtenerMonedasResponse 
    xmlns:ns1="urn:v1.001" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:tns="http://www.example.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <listaMonedas xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="tns:WSMoneda[21]">
    <item xsi:type="tns:WSMoneda">
        <id xsi:type="xsd:integer">1</id>
        <moneda xsi:type="xsd:string">LIBRA ESTERLINA</moneda>
        <dollar xsi:type="xsd:string">0.7767</dollar>
        <abr xsi:type="xsd:string">GBP</abr>
        <singPlur xsi:type="xsd:string">LIBRA:LIBRAS</singPlur>
        <caracter xsi:type="xsd:string">£</caracter>
        <flag16 xsi:type="xsd:string">Base64Img</flag16> 
        <flag24 xsi:type="xsd:string">Base64Img</flag24> 
        <flag32 xsi:type="xsd:string">Base64Img</flag32>   
     </item>
     <item xsi:type="tns:WSMoneda">
        <id xsi:type="xsd:integer">1</id>
        <moneda xsi:type="xsd:string">PESO MEXICANO</moneda>
        <dollar xsi:type="xsd:string">18.7000</dollar>
        <abr xsi:type="xsd:string">MXN</abr>
        <singPlur xsi:type="xsd:string">PESO:PESOS</singPlur>
        <caracter xsi:type="xsd:string">$</caracter>
        <flag16 xsi:type="xsd:string">Base64Img</flag16> 
        <flag24 xsi:type="xsd:string">Base64Img</flag24> 
        <flag32 xsi:type="xsd:string">Base64Img</flag32>   
     </item> 
  </listaMonedas>
</ns1:obtenerMonedasResponse>

记住,我建议你这个问题是为了更符合你的需求:
XPath to select element based on childs child value.

因此,您的 XPath 应该是:

XMLNodeList :=
  XMLDocument.SelectNodes('//listaMonedas/item[moneda/text()="LIBRA ESTERLINA"]');

意思是,您想要 select item 标签,其中包含 moneda 个带有 LIBRA ESTERLINA 文本的子标签。


此外,正如您期望的只有一个匹配项(不是吗?),您应该使用 SelectSingleNode 并且您的代码会简单得多:

XMLNode :=
  XMLDocument.SelectSingleNode('//listaMonedas/item[moneda/text()="LIBRA ESTERLINA"]');

id       :=  XMLNode.SelectSingleNode('id').Text;
moneda   :=  XMLNode.SelectSingleNode('moneda').Text;
dollar   :=  XMLNode.SelectSingleNode('dollar').Text;
abr      :=  XMLNode.SelectSingleNode('abr').Text;
singPlur :=  XMLNode.SelectSingleNode('singPlur').Text;
caracter :=  XMLNode.SelectSingleNode('caracter').Text;

MsgBox(id+moneda+dollar+abr+singPlur+caracter, mbInformation, MB_OK);