返回节点的所有父节点

发布于 2024-10-29 06:47:11 字数 1788 浏览 1 评论 0原文

我有一个类似 XML 结构的文件系统,现在我想获取 .我尝试了以下 XSLT,但它不起作用。我只收到这些错误:

警告: XSLTProcessor::transformToXml(): 模板: 在 C:\Users\Ludger\Documents\XAMPP\htdocs\CloudAmp\devel\php\localAudioFileLocationScanner.php 第 60 行

警告: XSLTProcessor::transformToXml(): #0 名称 //文件所在 C:\Users\Ludger\Documents\XAMPP\htdocs\CloudAmp\devel\php\localAudioFileLocationScanner.php 第 60 行

警告: XSLTProcessor::transformToXml(): #1 名称 //文件所在 C:\Users\Ludger\Documents\XAMPP\htdocs\CloudAmp\devel\php\localAudioFileLocationScanner.php 第 60 行

[...]

警告:XSLTProcessor::transformToXml(): xsltApplyXSLTTemplate:潜力 无限模板递归是 检测到。您可以调整xsltMaxDepth (--max深度)以提高 最大嵌套模板数 调用和变量/参数(当前 设置为 3000)。在 C:\Users\Ludger\DocumentsXA MPP\htdocs\CloudAmp\devel\php\localAudioFileLocationScanner.php 第 60 行

XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/dir">
        <xsl:apply-templates select="@name" />
        <xsl:apply-templates select="parent::dir" />
    </xsl:template>

    <xsl:template match="//file">
        <xsl:apply-templates select="@name" />
        <xsl:apply-templates select="parent::dir" />
    </xsl:template>
</xsl:stylesheet>

源 XML:

<root>
  <path val="C:/Users/">
    <file name="a.txt"/>
    <dir name="aaa">
      <file name="b.txt"/>
      <file name="c.txt"/>
    </dir>
    <dir name="bbb">
      <dir name="ccc">
        <file name="d.txt"/>
      </dir>
    </dir>
  </path>
</root>

我无法让它工作。如果你能帮助我那就太好了。

I have a filesystem like XML structure, and now I want to get the "filepath" of a . I tried the following XSLT, but it doesn't work. I only get these errors:

Warning:
XSLTProcessor::transformToXml():
Templates: in
C:\Users\Ludger\Documents\XAMPP\htdocs\CloudAmp\devel\php\localAudioFileLocationScanner.php
on line 60

Warning:
XSLTProcessor::transformToXml(): #0
name //file in
C:\Users\Ludger\Documents\XAMPP\htdocs\CloudAmp\devel\php\localAudioFileLocationScanner.php
on line 60

Warning:
XSLTProcessor::transformToXml(): #1
name //file in
C:\Users\Ludger\Documents\XAMPP\htdocs\CloudAmp\devel\php\localAudioFileLocationScanner.php on line 60

[...]

Warning: XSLTProcessor::transformToXml():
xsltApplyXSLTTemplate: A potential
infinite template recursion was
detected. You can adjust xsltMaxDepth
(--maxdepth) in order to raise the
maximum number of nested template
calls and variables/params (currently
set to 3000). in
C:\Users\Ludger\DocumentsXA
MPP\htdocs\CloudAmp\devel\php\localAudioFileLocationScanner.php
on line 60

XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/dir">
        <xsl:apply-templates select="@name" />
        <xsl:apply-templates select="parent::dir" />
    </xsl:template>

    <xsl:template match="//file">
        <xsl:apply-templates select="@name" />
        <xsl:apply-templates select="parent::dir" />
    </xsl:template>
</xsl:stylesheet>

Source XML:

<root>
  <path val="C:/Users/">
    <file name="a.txt"/>
    <dir name="aaa">
      <file name="b.txt"/>
      <file name="c.txt"/>
    </dir>
    <dir name="bbb">
      <dir name="ccc">
        <file name="d.txt"/>
      </dir>
    </dir>
  </path>
</root>

I can't get it working. It would be great if you can help me out.

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

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

发布评论

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

评论(2

魄砕の薆 2024-11-05 06:47:11

发生的情况是,您匹配任何 file 元素,然后将模板应用于其父 dir,该元素与元素的默认模板相匹配,该元素将模板应用于所有它的子级,导致同一文件的另一个匹配并开始无限递归。

(请注意,dir 元素的模板永远不会匹配任何内容,因为它只查找作为根节点子节点的 dir 元素,而您没有根节点的子节点.)

以下样式表:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="dir" mode="path">
        <xsl:value-of select="@name" />
        <xsl:text>/</xsl:text>
    </xsl:template>
    <xsl:template match="file">
        <xsl:apply-templates select="ancestor::dir" mode="path"/>
        <xsl:value-of select="@name" />
    </xsl:template>
</xsl:stylesheet>

产生以下输出:

a.txt
aaa/b.txt
aaa/c.txt
bbb/ccc/d.txt

编辑: 我认为,当可以避免回溯时,通常最好向前推进文档。以下样式表产生与上面相同的输出,但更高效、更优雅:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="dir">
        <xsl:param name="prev" select="''" />
        <xsl:apply-templates>
            <xsl:with-param name="prev" select="concat($prev, @name, '/')" />
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="file">
        <xsl:param name="prev" select="''" />
        <xsl:value-of select="concat($prev, @name)" />
    </xsl:template>
</xsl:stylesheet>

What's happening is that you're matching any file element, then applying templates to its parent dir, which is matched by the default template for elements, which applies templates to all of its children, resulting in another match of the same file and starting an infinite recursion.

(Note that your template for dir elements never matches anything, because it's looking only for dir elements that are a child of the root node, of which you have none.)

The following stylesheet:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="dir" mode="path">
        <xsl:value-of select="@name" />
        <xsl:text>/</xsl:text>
    </xsl:template>
    <xsl:template match="file">
        <xsl:apply-templates select="ancestor::dir" mode="path"/>
        <xsl:value-of select="@name" />
    </xsl:template>
</xsl:stylesheet>

Produces the following output:

a.txt
aaa/b.txt
aaa/c.txt
bbb/ccc/d.txt

Edit: I think it's generally better to push forward through the document when backtracking can be avoided. The following stylesheet produces the same output as above, but is more efficient and elegant:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="dir">
        <xsl:param name="prev" select="''" />
        <xsl:apply-templates>
            <xsl:with-param name="prev" select="concat($prev, @name, '/')" />
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="file">
        <xsl:param name="prev" select="''" />
        <xsl:value-of select="concat($prev, @name)" />
    </xsl:template>
</xsl:stylesheet>
迷离° 2024-11-05 06:47:11

此转换:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="file">
  <xsl:apply-templates mode="buildPath"
   select="ancestor::*[not(self::root or self::path)]"/>
  <xsl:value-of select="concat(@name, '
')"/>
 </xsl:template>

 <xsl:template match="*" mode="buildPath">
  <xsl:value-of select="concat(@name,'/')"/>
 </xsl:template>
</xsl:stylesheet>

当应用于提供的 XML 文档时:

<root>
    <path val="C:/Users/">
        <file name="a.txt"/>
        <dir name="aaa">
            <file name="b.txt"/>
            <file name="c.txt"/>
        </dir>
        <dir name="bbb">
            <dir name="ccc">
                <file name="d.txt"/>
            </dir>
        </dir>
    </path>
</root>

产生所需的正确结果:

a.txt
aaa/b.txt
aaa/c.txt
bbb/ccc/d.txt

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="file">
  <xsl:apply-templates mode="buildPath"
   select="ancestor::*[not(self::root or self::path)]"/>
  <xsl:value-of select="concat(@name, '
')"/>
 </xsl:template>

 <xsl:template match="*" mode="buildPath">
  <xsl:value-of select="concat(@name,'/')"/>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<root>
    <path val="C:/Users/">
        <file name="a.txt"/>
        <dir name="aaa">
            <file name="b.txt"/>
            <file name="c.txt"/>
        </dir>
        <dir name="bbb">
            <dir name="ccc">
                <file name="d.txt"/>
            </dir>
        </dir>
    </path>
</root>

produces the wanted, correct result:

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