我正在使用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/gortin看到输出。我出错的任何想法?我认为这与$ subIndi值有关,但是无论何时我尝试更改它都会出错。非常感谢任何帮助!
答案 0 :(得分:3)
听起来很完美!你能给我一个吗? 例?这是否意味着我可以保存 数据为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,但this article将向您展示如何使用上面的样式表转换XML。
您还可以通过在XML文件顶部添加样式表指令来链接样式表(请参阅for an example)。
答案 1 :(得分:0)
getElementsByTagName将为您提供所有节点,而不仅仅是直接的孩子:
$family = $indi->getElementsByTagName('family');
foreach ($family as $subIndi) {
outputIndi($subIndi);
}
您将重复为大孩子等调用outputIndi()。
以下是一个示例(来自另一个stackoverflow question):
for ($n = $indi->firstChild; $n !== null; $n = $n->nextSibling) {
if ($n instanceof DOMElement && $n->tagName == "family") {
outputIndi($n);
}
}
答案 2 :(得分:0)
替换此
$family = $indi->getElementsByTagName('family');
foreach ($family as $subIndi) {
outputIndi($subIndi);
}
由此
if(!empty($indi))
foreach($indi as $subIndi){
outputIndi($subIndi);
}
我意识到了 如果(因迪$&GT; hasChildNodes()) 比...更好 if(!empty($ indi))