使用 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()'。请注意,我假设您在同一棵树中只有一种类型的 Citizen
或 Service
,这似乎是合理的,因为您的示例文档引用了一个命名空间。
//*[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 这应该给你一个关于写好问题的教训。对于您以后的问题,请确保立即提供所有相关信息。
我有以下 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()'。请注意,我假设您在同一棵树中只有一种类型的 Citizen
或 Service
,这似乎是合理的,因为您的示例文档引用了一个命名空间。
//*[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
库,因为它们的行为可能令人惊讶。在您的特定情况下,可以原谅期望像
//Citizen
不会return任何东西,因为这些元素在默认命名空间中。通常,默认名称空间需要在 PHP 代码中重新声明,并提供给 XPath 引擎。但是 SimpleXML
忽略了默认命名空间——实际上是 "not so simple"。
1 这应该给你一个关于写好问题的教训。对于您以后的问题,请确保立即提供所有相关信息。