如何在输出中包含子元素的每个子元素? PHP

发布于 2025-01-06 09:17:07 字数 2875 浏览 0 评论 0原文

我有一个小型应用程序,它执行以下操作:

  • 允许用户上传 XML 文件
  • 将 XML 文件解析为数组以使用 $_SESSION
  • 显示用户可以选择查看的父元素名称列表
  • 解析数组以显示子元素选定的父元素

问题是每个 item 都可以有子元素,而子元素又可以有子元素,而子元素又可以有子元素……等等……而且这种情况可以无限期地持续下去。

如何在最终输出中包含子级的每个子级?

XML 文件看起来与此类似:

<thing>
  <parents>
    <parent>
      <name>parent 1</name>
      <categories>
        <category>
          <name>category 1</name>
          <items>
            <item>
              <name>item 1 (gen 1)</name>
              <items>
                <item>
                  <name>sub-item 1 (gen 2)</name>
                  <items>
                    <item>
                      <name>sub-sub-item 1 (gen 3)</name>
                      ...this could continue forever..
                    </item>
                  </items>
                </item>
              </items>
            </item>
          </items>
        </category>
      </categories>
    </parent>
  </parents>
</thing>

我已使用 PHP 的 SimpleXML 将 XML 解析为数组。每个文件都必须有父项、类别和第一代子项。下面的代码解析了这 3 个层次的结构,但除此之外我就迷失了。

$output .= '<ul>';
foreach($xml['parents'] as $parent){
  $output .= '<li>'.$parent['name'].'</li>';
  foreach($parent['categories']['category'] as $category){
    $output .= '<li>'.$category['name'].'</li>';
    foreach($category['items']['item'] as $item){
      $output .= '<li>'.$item['name'].'</li>';
      // here is where the $item can have children w/ children
      // who can have children who can have children... etc... forever.
      // (i.e. $item['items']['item'] as $generation2_items++...)
      //
      // I want to add them as another <li></li>...
      //
      // How can you account for unknown # of children?
    }
  }
}
$output .= '</ul>';
echo $output;

代码 $ 输出一个类似于以下内容的列表:

- parent 1
-- category 1
--- item 1 (gen 1)
---- sub item 1 (gen 2)
----- sub-sub item 1 (gen 3)
------- etc.
-------- etc.

如何确定每个项目的深度有多少个子元素,然后如何创建足够的循环来相应地解析...或通过另一种方式进行迭代?

感谢您的帮助。

解决方案

PHP递归函数解决了这个问题。这是我在遇到可能的无限重复部分时使用的:

function foo($element, $indent=0){
  $result .= '<li>';
  if($indent > 0){
    for($i=1;$i<=$indent;$i++){
      $result .= '&nbsp;&nbsp;&nbsp;&nbsp;';
    }
  }
  $result .= $element['name'].'</li>';
  if(isset($element['children']['child'])){
    $i++;
    foreach($element['children']['child'] as $child){
   $result .= foo($child, $i);
    }
  }
  return $result;
}    

$output .= foo($item);

I have a small application that does the following:

  • allows the user to upload an XML file
  • parses the XML file into an array to work with $_SESSION
  • displays a list of parent element names the user can choose to view
  • parses the array to display children of the selected parent elements

The issue is that every item can have children who can have children who can have children... etc... and this can go on indefinitely.

How can you include every child of a child in the final output?

The XML files can look similar to this:

<thing>
  <parents>
    <parent>
      <name>parent 1</name>
      <categories>
        <category>
          <name>category 1</name>
          <items>
            <item>
              <name>item 1 (gen 1)</name>
              <items>
                <item>
                  <name>sub-item 1 (gen 2)</name>
                  <items>
                    <item>
                      <name>sub-sub-item 1 (gen 3)</name>
                      ...this could continue forever..
                    </item>
                  </items>
                </item>
              </items>
            </item>
          </items>
        </category>
      </categories>
    </parent>
  </parents>
</thing>

I've parsed the XML into an array with PHP's SimpleXML. Every file must have a parent, category, and first generation child items. The following code parses through these 3 levels of structure, but beyond that I'm lost.

$output .= '<ul>';
foreach($xml['parents'] as $parent){
  $output .= '<li>'.$parent['name'].'</li>';
  foreach($parent['categories']['category'] as $category){
    $output .= '<li>'.$category['name'].'</li>';
    foreach($category['items']['item'] as $item){
      $output .= '<li>'.$item['name'].'</li>';
      // here is where the $item can have children w/ children
      // who can have children who can have children... etc... forever.
      // (i.e. $item['items']['item'] as $generation2_items++...)
      //
      // I want to add them as another <li></li>...
      //
      // How can you account for unknown # of children?
    }
  }
}
$output .= '</ul>';
echo $output;

The code $outputs a list similar to:

- parent 1
-- category 1
--- item 1 (gen 1)
---- sub item 1 (gen 2)
----- sub-sub item 1 (gen 3)
------- etc.
-------- etc.

How can you determine how many child elements deep each item goes and then how can you create enough loops to parse through accordingly... or iterate through another way?

Thanks for your help.

Solution

PHP recursion function solved it. Here's what I used when I got to the possible infinite repeating part:

function foo($element, $indent=0){
  $result .= '<li>';
  if($indent > 0){
    for($i=1;$i<=$indent;$i++){
      $result .= '    ';
    }
  }
  $result .= $element['name'].'</li>';
  if(isset($element['children']['child'])){
    $i++;
    foreach($element['children']['child'] as $child){
   $result .= foo($child, $i);
    }
  }
  return $result;
}    

$output .= foo($item);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤者何惧 2025-01-13 09:17:07

您可以为此使用递归函数。每个程序员都应该知道如何使用递归;如果您不会:请立即学习!

您基本上想要做的是创建一个函数,我们将其称为 foo(),它接受一项作为输入。 foo 将做两件事:

  1. 输出当前项目
  2. 对于每个子项,以子项作为输入调用自身。

正如我所说,创建递归函数非常有用,您应该学习和练习这个工具。例如,您可以将带有递归深度的第二个参数发送给 foo,这样您就可以输出具有不同缩进的子级。

You may use a recursive function for this. Every programmer should know how to use recursion; if you don't: go ahead and learn it right away!

What you basically want to do is to create a function, let's call it foo(), which takes one item as it's input. foo will do two things:

  1. Output the current item
  2. For each child, call itself with the child as input.

Creating recursive functions is, as I said, really useful and you should both learn and exercise this tool. You may for example send a second argument to foo with the depth of the recursion so you can output the children with different indentation.

粉红×色少女 2025-01-13 09:17:07

在伪代码中,递归节点遍历函数可能看起来像这样:

function traverse(node)
{
    print(node);

    if(node.hasChildren()) {
        foreach(node.children as child) {
            traverse(child);
        }
    }
}

希望有帮助! :)

In pseudo-code, a recursive node traversal function might look something like this:

function traverse(node)
{
    print(node);

    if(node.hasChildren()) {
        foreach(node.children as child) {
            traverse(child);
        }
    }
}

Hope that helps! :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文