使用 xpath 获取特定部分

Using xpath to grab a particular section

我有以下 xml 并且我正在尝试获取以下元素但不确定它是如何完成的:

Cashless catering Primary School

任何人都可以建议如何使用 refinement="Pupil" tag/attribute 使用 xpath 抓取这个吗?

<?xml version="1.0" encoding="utf-16" standalone="no"?>
<IntegrationExport xmlns="urn:NSCP-Integration-Export-v1">
<Data>
<Citizen messageId="331013" id="43018" authorisingId="1" messageTypeId="1" smartcardId="12345680201327582" serviceId="57" issuer="Primary School">
  <Services>
    <Service application="ISO File Handler" refinement="ISO File Handler" />
    <Service application="CCDA" refinement="CCDA">
      <Item name="SMARTCARDID">12345680201327582</Item>
      <Item name="IIN" />
      <Item name="CARDNO" />
      <Item name="ISSUE">7</Item>
      <Item name="TITLE" />
      <Item name="FORENAME">Jon</Item>
      <Item name="INITIALS" />
      <Item name="SURNAME">Doe</Item>
      <Item name="NAME">Jon Doe</Item>
      <Item name="DOB">2004-11-04 00:00:00</Item>
      <Item name="GENDER">1</Item>
      <Item name="Ethnic Origin">White Other</Item>
      <Item name="Faith" />
      <Item name="SEN / Disability" />
      <Item name="Language" />
      <Item name="DOBVERIFIED">1</Item>
      <Item name="FLAT" />
      <Item name="HOUSE NUMBER/NAME" />
      <Item name="Street" />
      <Item name="Locality" />
      <Item name="Postal Town" />
      <Item name="County" />
      <Item name="POSTCODE" />
      <Item name="LOCAL AUTHORITY" />
      <Item name="RESIDENT">R</Item>
      <Item name="UPRN" />
      <Item name="HOME TEL" />
      <Item name="WORK TEL" />
      <Item name="MOBILE" />
      <Item name="EMAIL" />
      <Item name="Password" />
      <Item name="EXPIRY DATE">2017-09-01 00:00:00</Item>
      <Item name="Reward points">90</Item>
      <Item name="UPN">E301207408111</Item>
      <Item name="ParentPay ID">4292111</Item>
      <Item name="PayPoint Account No" />
      <Item name="YEARGROUP">3</Item>
      <Item name="FORMNAME">RED</Item>
      <Item name="Acknowledgement" />
      <Item name="USERID" />
      <Item name="REWARDS DATE" />
      <Item name="BARCODE">00100048123</Item>
      <Item name="MEMBER ID" />
      <Item name="LEISURECODE" />
      <Item name="LEISUREDATE" />
    </Service>
    <Service application="Special Needs" refinement="Special Needs">
      <Item name="CUSTOM MESSAGE">Placeholder message for special needs application.</Item>
      <Item name="SCREEN COLOUR">00</Item>
      <Item name="FONT">00</Item>
      <Item name="CHARACTER SIZE">00</Item>
      <Item name="SPEECH OUTPUT">00</Item>
    </Service>
    <Service application="Cashless catering Primary School" refinement="Pupil" />
    <Service application="Splash" refinement="Splash">
      <Item name="USERNAME" />
      <Item name="INITIAL PASSWORD" />
    </Service>
  </Services>
</Citizen>

代码

$endpoint = "http://111.222.11.200/someUrl.asmx?WSDL";
$client = new SoapClient($endpoint, array('trace' => 1));
$xml = $client->GetCitizenData($arrValues);
$xml = (string)$xml->GetCitizenDataResult;

$xml = preg_replace('/(<\?xml[^?]+?)utf-16/i', 'utf-8', $xml);
$xml_element = simplexml_load_string($xml);

$nodes = $xml_element->xpath('/Citizen/Services/Service[@refinement="Pupil"]/@application');

当我转储节点数组时,我得到以下信息:

SimpleXMLElement Object ( [@attributes] => Array ( [application] => Cashless catering Primary School ) ) 

假设您已经为命名空间 urn:NSCP-Integration-Export-v1 注册了别名 x,只获取属性 "application":

//x:Citizen/x:Services/x:Service[@refinement='Pupil']/@application

编辑

如果您不能使用命名空间,您可以使用命名空间不可知论者 'local-name()'。请注意,我假设您在同一棵树中只有一种类型的 CitizenService,这似乎是合理的,因为您的示例文档引用了一个命名空间。

//*[local-name()='Citizen']//*[local-name()='Service' and @refinement='Pupil']/@application

所以,我们最终得出结论1,就 XPath 而言,您已经获得了正确的结果;您的路径表达式检索到正确的节点。

唯一的困难是评估路径表达式 return 是一个 数组 。当整个数组被转储时,您自然会得到比想要的字符串本身更多的东西。使用

var_dump($nodes[application]);

只会转储此数组中的第一项:

string(32) "Cashless catering Primary School"

使用 reset() 会做类似的事情:

<?php
$array = array( application => 'Cashless catering Primary School');
echo reset($array);
?>

array_values($array)[0].


但请注意,在许多情况下不鼓励使用 PHP 和 Java 的 SimpleXML 库,因为它们的行为可能令人惊讶。在您的特定情况下,可以原谅期望像

这样的 XPath 表达式
//Citizen

不会return任何东西,因为这些元素在默认命名空间中。通常,默认名称空间需要在 PHP 代码中重新声明,并提供给 XPath 引擎。但是 SimpleXML 忽略了默认命名空间——实际上是 "not so simple"。


1 这应该给你一个关于写好问题的教训。对于您以后的问题,请确保立即提供所有相关信息。