为什么我的递归循环创建了太多子项?

发布于 2024-10-07 11:37:46 字数 3115 浏览 0 评论 0原文

我正在使用 PHP 递归循环来解析 XML 文档以创建嵌套列表,但是由于某种原因,循环被破坏并在列表中创建元素的重复项以及空白元素。

XML(家谱数据列表)的结构如下:

        <?xml version="1.0" encoding="UTF-8"?>
<family>
<indi>
    <id>id1</id>
    <fn>Thomas</fn>
    <bday></bday>
    <dday></dday>
    <spouse></spouse>
    <family>
            <indi>
                   <id>id1</id>
                   <fn>Alexander</fn>
                   <bday></bday>
                   <dday></dday>
                   <spouse></spouse>
                  <family>
                  </family>
           </indi>
           <indi>
                   <id>id1</id>
                   <fn>John</fn>
                   <bday></bday>
                   <dday></dday>
                   <spouse></spouse>
                   <family>
                            <indi>
                                 <id>id1</id>
                                 <fn>George</fn>
                                 <bday></bday>
                                 <dday></dday>
                                 <spouse></spouse>
                                 <family>
                                 </family>
            </indi>
                   </family>
            </indi>
    </family>
</indi>
</family>

这是我的 PHP 循环,它加载 XML 文件,然后循环遍历它以创建嵌套的 ul:

<?php 
    function outputIndi($indi) {
        echo '<li>';
        $id = $indi->getElementsByTagName('id')->item(0)->nodeValue;
        echo '<span class="vcard person" id="' . $id . '">';

        $fn = $indi->getElementsByTagName('fn')->item(0)->nodeValue;
        $bday = $indi->getElementsByTagName('bday')->item(0)->nodeValue;

        echo '<span class="edit fn">' . $fn . '</span>';
        echo '<span class="edit bday">' . $bday . '</span>';
        // ...
        echo '</span>';
        echo '<ul>';
        $family = $indi->getElementsByTagName('family');
        foreach ($family as $subIndi) {
                outputIndi($subIndi);
            }
        echo '</ul></li>';
    }

    $doc = new DOMDocument();
    $doc->load('armstrong.xml');

    outputIndi($doc);

    ?>

编辑这里是所需的结果(嵌套列表,带有 ul 的表示家庭,li 表示个人)

<ul>
  <li>
    <span class="vcard">
      <span class="fn">Thomas</span>
      <span class="bday"></span>
      <span class="dday"></span>
      <ul>
             ... repeat for all ancestors ...
      </ul>
   <li>
<ul>

您可以在 http://chris-armstrong.com/ 查看输出戈廷。有什么想法我哪里出错了吗?我认为这与 $subIndi 值有关,但每当我尝试更改它时都会收到错误。非常感谢任何帮助!

I'm using a PHP recursive loop to parse through an XML document to create a nested list, however for some reason the loop is broken and creating duplicates of elements within the list, as well as blank elements.

The XML (a list of family tree data) is structured as follows:

        <?xml version="1.0" encoding="UTF-8"?>
<family>
<indi>
    <id>id1</id>
    <fn>Thomas</fn>
    <bday></bday>
    <dday></dday>
    <spouse></spouse>
    <family>
            <indi>
                   <id>id1</id>
                   <fn>Alexander</fn>
                   <bday></bday>
                   <dday></dday>
                   <spouse></spouse>
                  <family>
                  </family>
           </indi>
           <indi>
                   <id>id1</id>
                   <fn>John</fn>
                   <bday></bday>
                   <dday></dday>
                   <spouse></spouse>
                   <family>
                            <indi>
                                 <id>id1</id>
                                 <fn>George</fn>
                                 <bday></bday>
                                 <dday></dday>
                                 <spouse></spouse>
                                 <family>
                                 </family>
            </indi>
                   </family>
            </indi>
    </family>
</indi>
</family>

And here's my PHP loop, which loads the XML file then loops through it to create a nested ul:

<?php 
    function outputIndi($indi) {
        echo '<li>';
        $id = $indi->getElementsByTagName('id')->item(0)->nodeValue;
        echo '<span class="vcard person" id="' . $id . '">';

        $fn = $indi->getElementsByTagName('fn')->item(0)->nodeValue;
        $bday = $indi->getElementsByTagName('bday')->item(0)->nodeValue;

        echo '<span class="edit fn">' . $fn . '</span>';
        echo '<span class="edit bday">' . $bday . '</span>';
        // ...
        echo '</span>';
        echo '<ul>';
        $family = $indi->getElementsByTagName('family');
        foreach ($family as $subIndi) {
                outputIndi($subIndi);
            }
        echo '</ul></li>';
    }

    $doc = new DOMDocument();
    $doc->load('armstrong.xml');

    outputIndi($doc);

    ?>

EDIT here's the desired outcome (nested lists, with ul's signifying families and li's signifying individuals)

<ul>
  <li>
    <span class="vcard">
      <span class="fn">Thomas</span>
      <span class="bday"></span>
      <span class="dday"></span>
      <ul>
             ... repeat for all ancestors ...
      </ul>
   <li>
<ul>

You can see the output at http://chris-armstrong.com/gortin . Any ideas where I'm going wrong? I think it's something to do with the $subIndi value, but anytime I try and change it I get an error. Would really appreciate any help!

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

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

发布评论

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

评论(3

旧人 2024-10-14 11:37:46

听起来很完美!你能给我一个
例子?这是否意味着我可以拯救
数据为 XML,然后将其作为嵌套加载
ul 的?

是的,你完全可以这样做。这是一个呈现嵌套 UL 的 XSL:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
      <html>
      <body>
        <h2>Family tree</h2>
        <ul>
            <li><xsl:value-of select="indi/fn" /></li>

            <!-- apply-templates will select all the indi/family nodes -->
            <xsl:apply-templates select="indi/family" />
        </ul>
      </body>
      </html>
    </xsl:template>

    <xsl:template match="family">       
        <ul>
            <li>
                <div>
                    <xsl:value-of select="id" />: <xsl:value-of select="fn" />
                    (<xsl:variable name="bday" select="bday" />
                    to
                    <xsl:variable name="dday" select="dday" />)
                </div>
            </li>
            <!-- This node matches the 'family' nodes, and we're going to apply-templates on the inner 'family' node,
            so this is the same thing as recursion. -->
            <xsl:apply-templates select="family" />
        </ul>
    </xsl:template>
</xsl:stylesheet>

我不懂 php,但是 这篇文章 将向您展示如何使用上面的样式表转换 XML。

您还可以通过在 XML 文件顶部添加样式表指令来链接样式表(请参阅 示例)。

Sounds perfect! Could you give me an
example? Does this mean I can save the
data as XML, then load it in as nested
ul's?

Yes, you can do exactly that. Here's an XSL which renders nested UL's:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
      <html>
      <body>
        <h2>Family tree</h2>
        <ul>
            <li><xsl:value-of select="indi/fn" /></li>

            <!-- apply-templates will select all the indi/family nodes -->
            <xsl:apply-templates select="indi/family" />
        </ul>
      </body>
      </html>
    </xsl:template>

    <xsl:template match="family">       
        <ul>
            <li>
                <div>
                    <xsl:value-of select="id" />: <xsl:value-of select="fn" />
                    (<xsl:variable name="bday" select="bday" />
                    to
                    <xsl:variable name="dday" select="dday" />)
                </div>
            </li>
            <!-- This node matches the 'family' nodes, and we're going to apply-templates on the inner 'family' node,
            so this is the same thing as recursion. -->
            <xsl:apply-templates select="family" />
        </ul>
    </xsl:template>
</xsl:stylesheet>

I don't know php, but this article will show you how to transform XML using the style sheet above.

You can also link your style sheet by adding a stylesheet directive at the top of your XML file (see for an example).

逆蝶 2024-10-14 11:37:46

getElementsByTagName 将为您提供所有节点,而不仅仅是直接子节点:

$family = $indi->getElementsByTagName('family');
foreach ($family as $subIndi) {
    outputIndi($subIndi);
}

您将调用 outputIndi () 为孙子等反复。

这是一个示例(来自另一个 stackoverflow 问题):

for ($n = $indi->firstChild; $n !== null; $n = $n->nextSibling) {
    if ($n instanceof DOMElement && $n->tagName == "family") {
        outputIndi($n);
    }
}

getElementsByTagName will give you all nodes, not just immediate children:

$family = $indi->getElementsByTagName('family');
foreach ($family as $subIndi) {
    outputIndi($subIndi);
}

You will call outputIndi() for grand children, etc repeatedly.

Here is an example (from another stackoverflow question):

for ($n = $indi->firstChild; $n !== null; $n = $n->nextSibling) {
    if ($n instanceof DOMElement && $n->tagName == "family") {
        outputIndi($n);
    }
}
心凉怎暖 2024-10-14 11:37:46

替换这个

$family = $indi->getElementsByTagName('family');
foreach ($family as $subIndi) {
        outputIndi($subIndi);
    }

用这个

if(!empty($indi))
foreach($indi as $subIndi){  
     outputIndi($subIndi);
} 

我意识到
if($indi->hasChildNodes())

更好
if(!empty($indi))

Replace this

$family = $indi->getElementsByTagName('family');
foreach ($family as $subIndi) {
        outputIndi($subIndi);
    }

by this

if(!empty($indi))
foreach($indi as $subIndi){  
     outputIndi($subIndi);
} 

I realize
if($indi->hasChildNodes())
is better than
if(!empty($indi))

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