xml 的 Xpath 查询帮助

Xpath Query help for xml

我对 SOAPUI、XML 和编写 XPath 查询还很陌生。我使用 SOAP UI 从 REST API 获得 XML 输出。现在我必须创建一个 XPath 断言来验证是否存在当前 运行 的 Red Hat 映像,可以使用 operatingSystem id & state 找到它。但是我无法在输出的 SOAPUI 中断言。

你有什么建议吗?

似乎有不同的命名空间,其中一个 url 没有在 XML 中声明的命名空间 xmlns="http://testlab.example.net/schemas/server"

XML 提供如下:

<ServersWithState pageNumber="1" pageCount="2" totalCount="2" pageSize="250" 
  xmlns:ns16="http://testlab.example.net/schemas/storage" 
  xmlns="http://testlab.example.net/schemas/server" 
  xmlns:ns14="http://testlab.example.net/schemas/support" 
  xmlns:ns15="http://testlab.example.net/schemas/multigeo" 
  xmlns:ns9="http://testlab.example.net/schemas/admin" 
  xmlns:ns5="http://testlab.example.net/schemas/vip" 
  xmlns:ns12="http://testlab.example.net/schemas/serverbootstrap" 
  xmlns:ns13="http://testlab.example.net/schemas/backup" 
  xmlns:ns6="http://testlab.example.net/schemas/general" 
  xmlns:ns7="http://testlab.example.net/schemas/datacenter" 
  xmlns:ns10="http://testlab.example.net/schemas/whitelabel" 
  xmlns:ns8="http://testlab.example.net/schemas/manualimport" 
  xmlns:ns11="http://testlab.example.net/schemas/reset" 
  xmlns:ns2="http://testlab.example.net/schemas/directory" 
  xmlns:ns4="http://testlab.example.net/schemas/network" 
  xmlns:ns3="http://testlab.example.net/schemas/organization">
   <serverWithState id="d6fb8348-97ff-4169-a4f8-33ac12ecf6ff" location="Home_LAB">
      <name>test_server_windows</name>
      <description/>
      <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" type="WINDOWS"/>
      <cpuCount>2</cpuCount>
      <memoryMb>4096</memoryMb>
      <disk id="4ca8b248-573d-4210-819c-66c114ecea01" scsiId="0" sizeGb="32" speed="STANDARD" state="NORMAL"/>
      <sourceImageId>fbf3ad74-2b69-49c8-9a37-f963b3102d2c</sourceImageId>
      <networkId>9906ddd8-45aa-11e0-b7ea-0030487e0302</networkId>
      <machineName>10-157-116-11</machineName>
      <privateIp>10.157.116.11</privateIp>
      <created>2014-09-25T17:24:52.000Z</created>
      <isDeployed>true</isDeployed>
      <isStarted>true</isStarted>
      <state>NORMAL</state>
      <machineStatus name="vmwareToolsVersionStatus">
         <value>NEED_UPGRADE</value>
      </machineStatus>
      <machineStatus name="vmwareToolsRunningStatus">
         <value>RUNNING</value>
      </machineStatus>
      <machineStatus name="vmwareToolsApiVersion">
         <value>7303</value>
      </machineStatus>
   </serverWithState>
   <serverWithState id="ab271ab1-7daa-443b-bb21-a62e27a7b207" location="Home_LAB">
      <name>test_server_linux</name>
      <description/>
      <operatingSystem id="REDHAT564" displayName="REDHAT5/64" type="UNIX"/>
      <cpuCount>1</cpuCount>
      <memoryMb>2048</memoryMb>
      <disk id="41516cdb-1010-44bd-ba6e-a00bd2340974" scsiId="0" sizeGb="10" speed="STANDARD" state="NORMAL"/>
      <sourceImageId>0d6fdc8c-7529-4fb8-9028-8f133c7de2ae</sourceImageId>
      <networkId>9906ddd8-45aa-11e0-b7ea-0030487e0302</networkId>
      <machineName>10-157-116-12</machineName>
      <privateIp>10.157.116.12</privateIp>
      <created>2014-09-25T17:25:39.000Z</created>
      <isDeployed>false</isDeployed>
      <isStarted>false</isStarted>
      <state>FAILED_ADD</state>
      <status>
         <action>DEPLOY_SERVER</action>
         <requestTime>2014-09-25T17:25:39.000Z</requestTime>
         <userName>autotest</userName>
         <numberOfSteps>13</numberOfSteps>
         <updateTime>2014-09-25T17:38:00.000Z</updateTime>
         <step>
            <name>WAIT_FOR_CLONE_VM_TASK</name>
            <number>5</number>
            <percentComplete>91</percentComplete>
         </step>
         <failureReason>Could not complete network copy for file /vmfs/volumes/4b215b8c-44971195-4262-001cc4478f4b/T-RHEL-53-64-1-2-10-LAB0x/T-RHEL-53-64-1-2-10-LAB0x.vmdk</failureReason>
      </status>
   </serverWithState>
</ServersWithState>

我正在使用 PHP 评估 XPath,但您应该能够将其转换为您选择的任何语言:

<?php

$doc = new \DOMDocument();
$doc->load('in.xml');

$xpath = new \DOMXPath($doc);
$xpath->registerNamespace('n', 'http://testlab.example.net/schemas/server');
$result = $xpath->evaluate("boolean(
//n:serverWithState
    [starts-with(./n:operatingSystem/@id, 'REDHAT')]
    [./n:isStarted = 'true']
)");

var_dump($result);

您的示例输出 bool(false),如果您将 isStarted 的值更改为 true,则输出 bool(true)

boolean(//*[local-name()='operatingSystem'][starts-with(@id, 'REDHAT')]) 应该可以。如果您不能以其他方式指定要使用的命名空间,则必须使用 local-name() 函数 - 如果您想在 SoapUI 中这样做,您可以这样做:

declare namespace ns "http://testlab.example.net/schemas/server"
boolean(//ns:operatingSystem[starts-with(@id, 'REDHAT')])

如果您需要在其中捕获一个额外的节点(例如 stateisStarted),您可以这样做:

declare namespace ns "http://testlab.example.net/schemas/server"
boolean(//ns:operatingSystem[starts-with(@id, 'REDHAT') and ../ns:state='NORMAL'])

如果一个元素没有命名空间,它会从父元素继承命名空间。对于 SoapUI 断言 - 阅读 XML - 您可以对命名空间使用通配符,如下所示:

//*:operatingSystem[starts-with(@id, 'REDHAT')]

编辑: 要检查 SoapUI 断言中的 state,您的 XPath 表达式将是:

//*:operatingSystem[starts-with(@id, 'REDHAT')]/*:state

期望值是:

NORMAL

@RahulGupta:试试这个应该有用——

//*:serverWithState[*:operatingSystem[starts-with(@id, 'REDHAT')]]/*:state

   -> if you specify * in xpath no need to declare namespace in soapUI