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')])
如果您需要在其中捕获一个额外的节点(例如 state
或 isStarted
),您可以这样做:
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
我对 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')])
如果您需要在其中捕获一个额外的节点(例如 state
或 isStarted
),您可以这样做:
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