Динамически генерировать выражение XPath с использованием данных XML - PullRequest
4 голосов
/ 22 мая 2010

Я хотел бы динамически создавать выражения XPath в XSL, определяемом данными в файле XML. (т.е. данные XML «объединяются» для создания выражения XPath).

Пример данных XML:

<criteria>
    <criterion>AAA</criterion>
    <criterion>BBB</criterion>
    <criterion>CCC</criterion>
</criteria>

Пример того, как бы я хотел, чтобы выражение XPath выглядело так:

//AAA | //BBB | //CCC

И это динамическое создание должно быть сделано в XSL-файле.

Я довольно новичок в XSL (и его семье) и был бы признателен за общее руководство по решению этой проблемы.

Спасибо!

Edit: Чтобы обеспечить немного больше контекста .... Что мне нужно сделать, это сгенерировать XPath, который будет использоваться для создания second XSL, который преобразует совершенно другой XML-файл. Я знаю, как создать XSL из XSL, мне просто нужно динамически создавать выражения XPath. Если бы я мог изменять переменные (которые я читаю откуда-то еще, я не могу), я просто продолжал бы объединять узлы вместе, чтобы сформировать выражение. Затем я бы использовал имя переменной там, где мне было нужно. К сожалению, я не могу этого сделать, хотя ..: (

Ответы [ 3 ]

3 голосов
/ 22 мая 2010

Следующий пример создаст образец строки XPATH в качестве значения переменной «агентированный XPATH »при запуске с примером XML-файла:

    <xsl:variable name="generatedXPATH">
        <xsl:for-each select="/criteria/criterion">
            <xsl:text>//</xsl:text>
            <xsl:value-of select="." />
            <xsl:if test="position()!=last()">
                <xsl:text> | </xsl:text>
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>

Эту переменную можно использовать в таблице стилей, которая создает таблицу стилей длясоздайте шаблон @match значений следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xslt="http://www.w3.org/1999/XSL/TransformAlias"
    version="1.0">
    <xsl:namespace-alias stylesheet-prefix="xslt" result-prefix="xsl"/>
    <xsl:output indent="yes" />
    <xsl:template match="/">
        <xsl:variable name="generatedXPATH">
            <xsl:for-each select="/criteria/criterion">
                <xsl:text>//</xsl:text>
                <xsl:value-of select="." />
                <xsl:if test="position()!=last()">
                    <xsl:text> | </xsl:text>
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>

        <xslt:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
            <xslt:template>
                <xsl:attribute name="match">
                    <xsl:value-of select="$generatedXPATH" />
                </xsl:attribute>
                <xsl:comment>Do something special, like select the value of the matched elements</xsl:comment>
                <xslt:value-of select="." />
            </xslt:template>
        </xslt:stylesheet>
    </xsl:template>

</xsl:stylesheet>

При запуске с образцом XML создает следующую таблицу стилей:

<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="//AAA | //BBB | //CCC">
<!--Do something special, like select the value of the matched elements-->
<xsl:value-of select="." />
</xsl:template>
</xsl:stylesheet>
2 голосов
/ 22 мая 2010

Можно динамически создавать выражения XPath в XSLT, но динамическая оценка этих выражений невозможна (по крайней мере, до XSLT 2.1 ).

ЧтоВы можете сделать это по-другому в XSLT.

Вот пример:

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

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <my:criteria>
  <criterion>a</criterion>
  <criterion>b</criterion>
  <criterion>c</criterion>
 </my:criteria>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="*[name()=document('')/*/my:criteria/*]">
   <xsl:element name="{name()}-{name()}" namespace="{namespace-uri()}">
     <xsl:apply-templates select="node()|@*"/>
   </xsl:element>
 </xsl:template>
</xsl:stylesheet>

при применении к этому документу XML :

<t>
  <a>
    <x/>
    <y/>
    <b>
      <c/>
      <d/>
    </b>
  </a>
</t>

производит :

<t>
    <a-a>
        <x></x>
        <y></y>
        <b-b>
            <c-c></c-c>
            <d></d>
        </b-b>
    </a-a>
</t>

То есть мы только специальным образом обрабатывали любой элемент (в любом месте документа), имя которого было a или b или c.

0 голосов
/ 22 мая 2010

Вы не можете сделать это динамически с xsl или xpath. Вам придется использовать php или что-то еще (зависит от того, где вы используете это). Если у вас ограниченный набор узлов, вы можете использовать // AAA | // BBB | // CCC, и он будет работать, хотя это не очень полезно, если вы хотите, чтобы он работал на множестве разных узлов.

См. здесь для получения дополнительной информации о XPath.

Edit: Боже, ты редактировал это.

Для этого используйте / критерии / [критерий = ААА].

Редактировать снова:

запрос должен быть: "/criteria/[criterion=AAA] | criteria/[criterion=BBB] | criteria/[criterion=CCC]". Вы можете перефразировать это, чтобы быть более эффективным, хотя я забыл как. Посмотрите этот урок , чтобы увидеть, как это делается. Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...