将多维数组转换为XML,然后使用递归XSLT函数



我在PHP中有一个函数,它从给定路径中检索所有目录和文件。这将返回一个像

这样的数组:
array(
    "dirname1" => array(
        "dirname2" => array(
            "dirname3" => array(
                "0" => "file1",
                "1" => "file2",
                "2" => "file3"
            ),
            "0" => "file4",
            "1" => "file5",
            "2" => "file6",
            "dirname4" => array(
                "0" => "file7",
                "1" => "file8"
            )
        ),
        "0" => "file9",
        "1" => "file10"
    ),
    "0" => "file11",
    "1" => "file12",
    "2" => "file13"
);

我最后需要的是一个多维(不知道是否准确)列表,其中<ul /><li />是用XSLT 1.0从XML文件生成的,如:

<ul>
    <li class="dirname">
        dirname1
        <ul>
            <li class="dirname">
                Dirname2
                <ul>
                    <li class="dirname">
                        Dirname3
                        <ul>
                            <li>file1</li>
                            <li>file2</li>
                            <li>file3</li>
                        </ul>
                    </li>
                    <li>file4</li>
                    <li>file5</li>
                    <li>file6</li>
                    <li class="dirname">
                        dirname4
                        <ul>
                            <li>file7</li>
                            <li>file8</li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li>file9</li>
            <li>file10</li>
        </ul>
    </li>
    <li>file11</li>
    <li>file12</li>
    <li>file13</li>
</ul>

最后,在每个<li />中,我需要<a />中的路径,如:

<li class="dirname"><a href="/dirname1">dirname1</a></li>
<li><a href="/dirname1/dirname2/dirname3/file1">file1</a></li>
<li><a href="/dirname1/file9">file9</a></li>

实际上我没有需要转换的XML,因为我不知道什么结构可以很好地将其转换为XSLT 1.0。我有<a />内部的路径。如果有必要,我可以用PHP来做,我可以在PHP中检测它什么时候是目录,什么时候不是,我们也可以在XML上添加一些东西来检测class="dirname"

我希望我已经提供了足够的信息让你理解我。

提前感谢!

隧道参数:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:param name="pPath"/>
        <xsl:copy>
            <xsl:apply-templates select="node()|@*">
                <xsl:with-param name="pPath" select="$pPath"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="li[@class='dirname']">
        <xsl:param name="pPath"/>
        <xsl:call-template name="identity">
            <xsl:with-param name="pPath"
             select="concat($pPath,'/',normalize-space(text()[1]))"/>
        </xsl:call-template>
    </xsl:template>
    <xsl:template match="text()">
        <xsl:param name="pPath"/>
        <xsl:call-template name="text">
            <xsl:with-param name="pPath"
             select="concat($pPath,'/',normalize-space())"/>
        </xsl:call-template>
    </xsl:template>
    <xsl:template match="li[@class='dirname']/text()" name="text">
        <xsl:param name="pPath"/>
        <a href="{$pPath}">
            <xsl:value-of select="."/>
        </a>
    </xsl:template>
</xsl:stylesheet>
输出:

<ul>
    <li class="dirname">
        <a href="/dirname1">
            dirname1
        </a>
        <ul>
            <li class="dirname">
                <a href="/dirname1/Dirname2">
                    Dirname2
                </a>
                <ul>
                    <li class="dirname">
                        <a href="/dirname1/Dirname2/Dirname3">
                            Dirname3
                        </a>
                        <ul>
                            <li>
                                <a href="/dirname1/Dirname2/Dirname3/file1"
                                >file1</a>
                            </li>
                            <li>
                                <a href="/dirname1/Dirname2/Dirname3/file2"
                                >file2</a>
                            </li>
                            <li>
                                <a href="/dirname1/Dirname2/Dirname3/file3"
                                >file3</a>
                            </li>
                        </ul>
                    </li>
                    <li>
                        <a href="/dirname1/Dirname2/file4">file4</a>
                    </li>
                    <li>
                        <a href="/dirname1/Dirname2/file5">file5</a>
                    </li>
                    <li>
                        <a href="/dirname1/Dirname2/file6">file6</a>
                    </li>
                    <li class="dirname">
                        <a href="/dirname1/Dirname2/dirname4">
                            dirname4
                        </a>
                        <ul>
                            <li>
                                <a href="/dirname1/Dirname2/dirname4/file7"
                                >file7</a>
                            </li>
                            <li>
                                <a href="/dirname1/Dirname2/dirname4/file8"
                                >file8</a>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li>
                <a href="/dirname1/file9">file9</a>
            </li>
            <li>
                <a href="/dirname1/file10">file10</a>
            </li>
        </ul>
    </li>
    <li>
        <a href="/file11">file11</a>
    </li>
    <li>
        <a href="/file12">file12</a>
    </li>
    <li>
        <a href="/file13">file13</a>
    </li>
</ul>

PHP部分

function ulRenderer($dirs, $path = array()) {
    echo '<ul>';
    foreach ($dirs as $key => $value) {
        if (is_array($value)) {
            printf(
                '<li class="dirname"><a href="%s">%s</a>',
                implode('/', $path),
                $key
            );
            ulRenderer($value, array_merge(
                $path, array($key)
            ));
            echo '</li>';
        }
        else {
            printf(
                '<li><a href="%s/%s">%s</a></li>',
                implode('/', $path),
                $value, $value
            );
        }
    }
    echo '</ul>';
}
$dirs = array(
    "dirname1" => array(
        "dirname2" => array(
            "dirname3" => array(
                "0" => "file1",
                "1" => "file2",
                "2" => "file3"
            ),
            "0" => "file4",
            "1" => "file5",
            "2" => "file6",
            "dirname4" => array(
                "0" => "file7",
                "1" => "file8"
            )
        ),
        "0" => "file9",
        "1" => "file10"
    ),
    "0" => "file11",
    "1" => "file12",
    "2" => "file13"
);

ulRenderer($dirs);

XML/XSL部分

dirs.xml

<?xml version="1.0" encoding="UTF-8" ?>
<root>
    <dir name="dirname1">
        <dir name="dirname2">
            <dir name="dirname3">
                <file>file1</file>
                <file>file2</file>
                <file>file3</file>
            </dir>
            <dir name="dirname4">
                <file>file4</file>
                <file>file5</file>
            </dir>
            <file>file6</file>
            <file>file7</file>
            <file>file8</file>
        </dir>
        <file>file11</file>
        <file>file12</file>
        <file>file13</file>
    </dir>
</root>

dirs.xslt

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="dir">
        <ul>
            <li>
                <a>
                    <xsl:attribute name="href">
                        <xsl:call-template name="path" />
                    </xsl:attribute>
                    <xsl:value-of select="@name" />
                </a>
                <xsl:apply-templates />
            </li>
        </ul>
    </xsl:template>
    <xsl:template match="file">
        <li>
            <a>
                <xsl:attribute name="href">
                    <xsl:call-template name="path" />
                </xsl:attribute>
                <xsl:value-of select="." />
            </a>
        </li>
    </xsl:template>
    <xsl:template name="path">
        <xsl:if test="parent::dir">
            <xsl:for-each select="ancestor::dir">
                <xsl:sort select="position()" order="ascending"/>
                <xsl:value-of select="@name" />
                <xsl:text>/</xsl:text>
            </xsl:for-each>
        </xsl:if>
        <xsl:choose>
            <xsl:when test="name() = 'dir'">
                <xsl:value-of select="@name" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="." />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

和php再次

$dom = new DOMDocument;
$dom->load('dirs.xml');
$xsl = new DOMDocument;
$xsl->load('dirs.xslt', LIBXML_NOCDATA);
$xslt = new XSLTProcessor();
$xslt->importStylesheet($xsl);
echo $xslt->transformToXML($dom);

相关内容

最新更新