Я обрабатываю файл XML, который в упрощенном виде выглядит примерно так:
<resources>
<resource id="a">
<dependency idref="b"/>
<!-- some other stuff -->
</resource>
<resource id="b">
<!-- some other stuff -->
</resource>
</resources>
Таблица стилей XSLT должна обрабатывать определенный интересующий нас ресурс, который я назову корневой ресурс и все рекурсивные зависимости.Зависимости - это другие ресурсы, однозначно идентифицируемые по их атрибуту id
.
Не имеет значения, обрабатывается ли ресурс дважды, хотя предпочтительно обрабатывать каждый требуемый ресурс только один раз.Также не имеет значения, в каком порядке обрабатываются ресурсы.
Важно, чтобы only ресурс root и его рекурсивные зависимости обрабатывались.Мы не можем просто обработать все ресурсы и покончить с этим.
Наивная реализация выглядит следующим образом:
<xsl:key name="resource-id" match="resource" use="@id"/>
<xsl:template match="resource">
<!-- do whatever is required to process the resource. -->
<!-- then handle any dependencies -->
<xsl:apply-templates select="key('resource-id', dependency/@idref)"/>
</xsl:template>
Эта реализация отлично работает для примера выше, а также вмного реальных случаев.Недостатком является то, что он часто обрабатывает один и тот же ресурс более одного раза, но, как указано выше, это не очень важно.
Проблема в том, что иногда ресурсы имеют циклические зависимости:
<resources>
<resource id="a">
<dependency idref="b"/>
<dependency idref="d"/>
</resource>
<resource id="b">
<dependency idref="c"/>
</resource>
<resource id="c">
<dependency idref="a"/>
</resource>
<resource id="d"/>
</resources>
Если вы используете наивную реализацию для обработки этого примера и начинаете с обработки a , b или c , вы получаете бесконечную рекурсию.
К сожалению, я не могу контролировать входные данные, и в любом случае циклические зависимости полностью допустимы и разрешены соответствующей спецификацией.
Я придумал различные частичные решения, но ничего, что работало во всех случаях.
Идеальным решением будет общий подход к предотвращению обработки узла более одного раза, но я не думаю, что это возможно.На самом деле, я подозреваю, что всю эту проблему невозможно решить.
Если это поможет, у меня будет доступно большинство EXSLT (включая функции).При необходимости я также могу предварительно обработать ввод с помощью любого количества других XSLT-сценариев, хотя предпочтительно не выполнять чрезмерную предварительную обработку ресурсов, которые не попадут в вывод.
Что я могу 'Для этого нужно перейти на другой язык (по крайней мере, без существенной реинжиниринга).Я также не могу использовать XSLT 2.0.
Есть идеи?