在 PHP 中过滤子标签上的 XML 并返回父标签

Posted

技术标签:

【中文标题】在 PHP 中过滤子标签上的 XML 并返回父标签【英文标题】:Filter XML on child tag in PHP and return parent tags 【发布时间】:2021-03-27 09:24:00 【问题描述】:

正如标题所述,我有一个如下所示的 XML,其中一个帐户展开以查看内容。

<?xml version="1.0" encoding="utf-8"?>
<eExact
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="eExact-XML.xsd">
  <Accounts>
    <Account code="0" searchcode="" status="A" > </Account>
    <Account code="1" searchcode="" status="A" > </Account>
    <Account code="3" searchcode="" status="C" > </Account>
    <Account code="4" searchcode="" status="C" > </Account>
    <Account code="2" searchcode="" status="C" >
      <Name>Company 1</Name>
      <Phone>684564</Phone>
      <Email>info@company1.com</Email>
      <Contact number="2090075" gender="M" default="1" ID="2449ce5d-41b3-4f80-bab3-d13f6687dfe4">
        <LastName>Doe</LastName>
        <FirstName>Tom</FirstName>
        <Phone>44546456456e</Phone>
        <Email>tom.doe@company1.com</Email>
      </Contact>
      <Address type="SIV" default="1" ID="41bde841-afde-4f5d-9cd0-a12ecf6f6777">
        <AddressLine1>adress</AddressLine1>
        <PostalCode>10000</PostalCode>
        <City>TheCity</City>
        <Contact number="2090075" ID="2449ce5d-41b3-4f80-bab3-d13f6687dfe4" />
      </Address>
      <VATNumber>a_VAT_number_XXXX</VATNumber>
      <VATLiability>L</VATLiability>
      <SalesCurrency code="EUR" />
      <PurchaseCurrency code="EUR" />
    </Account>
  </Accounts>
  <Topics>
    <Topic code="Accounts" ts_d="0x000000006517487D" count="5" pagesize="1000" />
  </Topics>
  <Messages />
</eExact>

我要做的是返回状态为 C 并在 VATNumber 标记中包含值的帐户。有些帐户不包含 VATNumber 中的值,所以我希望那些被过滤掉或不返回。

到目前为止,我设法退回了 C 帐户,但没有过滤增值税号。

$document = new DOMDocument();
$document->loadXML($response);
$xpath = new DOMxpath($document);


foreach ($xpath->evaluate('(/eExact/Accounts/Account[@status="C"])') as $account)  

$json[] = [

   'email' => $xpath->evaluate('string(Contact[@default="1"]/Email)', $account),
    //'username' => $xpath->evaluate('string(Contact[@default="1"]/FirstName)', $account),
    'first_name' => $xpath->evaluate('string(Contact[@default="1"]/FirstName)', $account),
    'last_name' => $xpath->evaluate('string(Contact[@default="1"]/LastName)', $account),
    'billing' => [
      'first_name' => $xpath->evaluate('string(Contact[@default="1"]/FirstName)', $account),
      'last_name' => $xpath->evaluate('string(Contact[@default="1"]/LastName)', $account),
      'postcode'=> $xpath->evaluate('string(Address[@default="1"]/PostalCode)', $account),
      'VATNumber' => $xpath->evaluate('string(VATNumber)', $account),
    ],
    ];
    // ...




$customer = json_encode($json, JSON_PRETTY_PRINT);
$customers =   "\"create\": $customer \t";
// echo $customer;
echo $customers;

它给了我这个输出:

Key OK"create": [
    
        "email": "john.doe@company2.com",
        "first_name": "John",
        "last_name": "Doe",
        "billing": 
            "first_name": "John",
            "last_name": "Doe",
            "postcode": "",
            "VATNumber": ""
        
    ,
    
        "email": "steve.known@company3.com",
        "first_name": "Steve",
        "last_name": "Known",
        "billing": 
            "first_name": "Steve",
            "last_name": "Known",
            "postcode": "",
            "VATNumber": ""
        
    ,
    
        "email": "tom.doe@company1.com",
        "first_name": "Tom",
        "last_name": "Doe",
        "billing": 
            "first_name": "Tom",
            "last_name": "Doe",
            "postcode": "9200",
            "VATNumber": "a_VAT_number_XXXX"
        
    

我该如何做到这一点,以使 John 和 Steve 不会因为他们的增值税号为空而出现?

我假设在创建数组之前我需要先过滤。

【问题讨论】:

【参考方案1】:

如果值为not empty,您只需要一个 if 语句测试。

    if (!empty($xpath->evaluate('string(VATNUMBER)', $account))) 
        $json[] = [

        'email' => $xpath->evaluate('string(Contact[@default="1"]/Email)', $account),
         //'username' => $xpath->evaluate('string(Contact[@default="1"]/FirstName)', $account),
         'first_name' => $xpath->evaluate('string(Contact[@default="1"]/FirstName)', $account),
         'last_name' => $xpath->evaluate('string(Contact[@default="1"]/LastName)', $account),
         'billing' => [
          'first_name' => $xpath->evaluate('string(Contact[@default="1"]/FirstName)', $account),
          'last_name' => $xpath->evaluate('string(Contact[@default="1"]/LastName)', $account),
          'postcode'=> $xpath->evaluate('string(Address[@default="1"]/PostalCode)', $account),
          'VATNumber' => $xpath->evaluate('string(VATNumber)', $account),
         ],
        ];
        // ...
        
    

只要我的 php 没有完全付诸东流,将 $json[] = [ 封装在 If 语句中将测试该值是否为 empty,如果是,则将其从结果中省略。

【讨论】:

【参考方案2】:

您可以扩展您的初始 XPath 表达式以包括检查非空增值税号,以便它只处理这些元素...

/eExact/Accounts/Account[@status="C" and VATNumber/text()]

我还将初始化$json,就好像没有记录一样,你会得到一个未定义的变量错误。所以...

$json = [];
foreach ( $xpath->query('/eExact/Accounts/Account[@status="C" and VATNumber/text()]') as $account) 

【讨论】:

/eExact/Accounts/Account[@status="C" and normalize-space(VATNumber) != ""]

以上是关于在 PHP 中过滤子标签上的 XML 并返回父标签的主要内容,如果未能解决你的问题,请参考以下文章

解析具有相同父子标签的 XML,然后最好使用 SAX 解析器将父标签的值链接到子标签

Python 提取子标签不一致的 XML 数据

如何使父标签和子标签在b-form-checkbox上具有onclick而不重复

怎么用js代码复制父标签底下子标签以及样式,再将子标签加入到父标签中

Soundcloud API - 轨道上的地理标签过滤返回 503 服务不可用

如何循环多个子文件夹并根据特定的 XML 标签重命名文件?