Вернуть всех родителей узла - PullRequest
1 голос
/ 04 апреля 2011

У меня есть файловая система, похожая на структуру XML, и теперь я хочу получить "filepath" для a.Я попробовал следующий XSLT, но он не работает.Я получаю только эти ошибки:

Предупреждение: XSLTProcessor :: transformToXml (): Шаблоны: в C: \ Users \ Ludger \ Documents \ XAMPP \ htdocs \ CloudAmp \ devel \ php \ localAudioFileLocationScanner.php onстрока 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 (--maxdepth), чтобы увеличить максимальное количество вложенных вызовов шаблонов и переменных / параметров (в настоящее время установлено на 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>

Я не могу заставить его работать.Было бы здорово, если бы вы могли мне помочь.

Ответы [ 2 ]

1 голос
/ 04 апреля 2011

Происходит следующее: вы сопоставляете любой элемент file, затем применяете шаблоны к его родительскому элементу dir, который соответствует шаблону по умолчанию для элементов, который применяет шаблоны ко всем его дочерним элементам, что приводит к другому совпадению того же file и начала бесконечной рекурсии.

(Обратите внимание, что ваш шаблон для элементов 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>
0 голосов
/ 04 апреля 2011

Это преобразование:

<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, '&#xA;')"/>
 </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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...