php simplexml 分组对象

php simplexml grouping objects

在开始之前我想说我是一个菜鸟,不会将 XML 读入 PHP 但到目前为止我已经设法加载 XML 并将数据显示到 PHP 页。 我的下一个测试是对项目进行分组。

这是一个 XML 片段:

    <MailboxDatabases>
      <MailboxDatabase>
        <DatabaseName>DB01</DatabaseName>
        <Status>Healthy</Status>
        <MailboxServer>MB08</MailboxServer>
        <ActiveDatabaseCopy>mb07</ActiveDatabaseCopy>
        <ActivationSuspended>False</ActivationSuspended>
        <SinglePageRestore>0</SinglePageRestore>
        <ContentIndexState>Healthy</ContentIndexState>
        <Active>false</Active>
      </MailboxDatabase>
      <MailboxDatabase>
        <DatabaseName>DB01</DatabaseName>
        <Status>Healthy</Status>
        <MailboxServer>MB07</MailboxServer>
        <ActiveDatabaseCopy>mb07</ActiveDatabaseCopy>
        <ActivationSuspended>False</ActivationSuspended>
        <SinglePageRestore>0</SinglePageRestore>
        <ContentIndexState>Healthy</ContentIndexState>
        <Active>true</Active>
      </MailboxDatabase>
    <MailboxDatabases>
      <MailboxDatabase>
        <DatabaseName>DB02</DatabaseName>
        <Status>Healthy</Status>
        <MailboxServer>MB08</MailboxServer>
        <ActiveDatabaseCopy>mb07</ActiveDatabaseCopy>
        <ActivationSuspended>False</ActivationSuspended>
        <SinglePageRestore>0</SinglePageRestore>
        <ContentIndexState>Healthy</ContentIndexState>
        <Active>true</Active>
      </MailboxDatabase>
      <MailboxDatabase>
        <DatabaseName>DB02</DatabaseName>
        <Status>Healthy</Status>
        <MailboxServer>MB07</MailboxServer>
        <ActiveDatabaseCopy>mb07</ActiveDatabaseCopy>
        <ActivationSuspended>False</ActivationSuspended>
        <SinglePageRestore>0</SinglePageRestore>
        <ContentIndexState>Healthy</ContentIndexState>
        <Active>false</Active>
      </MailboxDatabase>
    </MailboxDatabases>

如您所见,"DatabaseName" 在两个项目中相同,但 "Active" 不同。 我想要做的是在 php 中显示上面的 xml like

DB01 - MB08 - 错误 | DB01 - MB07 - 真

DB02 - MB08 - 真 | DB01 - MB07 - 错误

使用以下元素 (数据库)-(邮箱服务器)-(活动)| ...

请有人帮助我,也请尝试解释代码。

总体攻略:

  1. 创建唯一组列表,即 <DatabaseName>
  2. select 属于一个组的所有 <MailboxDatabase> 并回应他们的 <MailboxServer><Active>
  3. 继续下一组并转到第 2 步,直到遍历所有组。

是时候从 XML 中学习 selecting 某些节点了,最好用 xpath 来完成。简而言之,xpath 用于 XML 就像 SQL 用于数据库。

假设您有一个 SimpleXML 对象准备就绪:

$xml = simplexml_load_string($x); // assume XML in $x

创建唯一组列表

获取数组中的所有 <DatabaseName>:

$groups = $xml->xpath("/MailboxDatabases/MailboxDatabase/DatabaseName");

$groups 现在包含一个 SimpleXML 元素的数组,所以让我们做一些数组魔术将它们转换为字符串:

$groups = array_map("strval", $groups);

结果(var_dump):

array(4) {
  [0]=>
  string(4) "DB01"
  [1]=>
  string(4) "DB01"
  [2]=>
  string(4) "DB02"
  [3]=>
  string(4) "DB02"
}

更多数组魔法:通过翻转键和值使其成为唯一列表,键必须是唯一的,因此重复项将被删除。然后再翻转:

$groups = array_flip(array_flip($groups));

结果:

array(2) {
  [1]=>
  string(4) "DB01"
  [3]=>
  string(4) "DB02"
}

就是这样。写成一行:

$groups = array_flip(array_flip(array_map("strval", $xml->xpath("//MailboxDatabase/DatabaseName"));

顺便说一句:xpath 语句开头的 // 是一个通配符

select 节点分组

再次 xpath,这次的条件是 select 只有共享相同 <DatabaseName> 的那些 <MailboxDatabase>。注意 [] 中的条件:

$elements = $xml->xpath("/MailboxDatabases/MailboxDatabase[DatabaseName = '$group']");

现在遍历 $groups:

foreach ($groups as $group) {

    echo "group $group:" . PHP_EOL;
    $elements = $xml->xpath("//MailboxDatabase[DatabaseName = '$group']");

    foreach ($elements as $e)
        echo "  " . $e->MailboxServer . ": " . $e->Active . PHP_EOL;

    echo PHP_EOL;
} 

结果:

group DB01:
  MB08: false
  MB07: true

group DB02:
  MB08: true
  MB07: false

看到它工作:https://eval.in/321935