Атрибут оценки XSL с переменными

Я хотел бы использовать файл xsl для отображения и оценки файла xml. Файл XML содержит количество частей, которые имеют заголовок, описание, изображение и количество. Но эта сумма зависит от некоторых переменных, которые я объявлю в файле XSL. Но в этом случае я должен вычислить выражение из XML в файле XSL. Есть ли способ сделать это?

См. пример: (выражения в @amount должны оцениваться с помощью переменных из XML)

XML:

<partslist>         
<part value="1" amount="$variable1" visible="true">     
    <title> 
        <nl>Onderdeel 1</nl>
        <fr>Partie 1</fr>
        <en>Part 1</en>
        <de>Teil 1</de>
    </title>    
    <image src="images/partslist/part1.jpg"/>   
</part>     
<part value="2" amount="$variable1 * $variable2" visible="true">        
    <title> 
        <nl>Onderdeel 2</nl>
        <fr>Partie 2</fr>
        <en>Part 2</en>
        <de>Teil 2</de>
    </title>    
    <image src="images/partslist/part2.jpg"/>   
</part> 
<part value="3" amount="$variable3" visible="true">     
    <title> 
        <nl>Onderdeel 3</nl>
        <fr>Partie 3</fr>
        <en>Part 3</en>
        <de>Teil 3</de>
    </title>    
    <image src="images/partslist/part3.jpg"/>   
</part> 
<part value="4" amount="$variable1 + $variable3" visible="true">        
    <title> 
        <nl>Onderdeel 4</nl>
        <fr>Partie 4</fr>
        <en>Part 4</en>
        <de>Teil 4</de>
    </title>    
    <image src="images/partslist/part4.jpg"/>   
</part> 
</partslist>            

XSL:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="/">
    <html>
        <head>
            <link rel="stylesheet" href="style.css" type="text/css"/>
        </head>
        <body>
            <xsl:variable name="variable1" select="1" />
            <xsl:variable name="variable2" select="2" />
            <xsl:variable name="variable3" select="3" />

            <div class="np">
                <H2>Parts List</H2>
                <table border ="1">
                    <tr>
                        <th style="width:15%;">ID</th>
                        <th style="width:15%;">Amount</th>
                        <th style="width:40%;">Description</th>
                        <th style="width:30%;">Image</th>
                    </tr>
                    <xsl:for-each select="partslist/part">
                        <tr>
                            <td><xsl:value-of select="@value" /></td>
                            <td><xsl:value-of select="@amount"/></td>
                            <td><xsl:value-of select="title/nl"/></td>
                            <td><img style="width:100%;" src="{image/@src}"/></td>
                        </tr>
                    </xsl:for-each>
                </table>
            </div>
        </body>
    </html>
</xsl:template>
</xsl:stylesheet>

заранее спасибо


person Pecoris    schedule 11.12.2017    source источник
comment
Пожалуйста, не могли бы вы уточнить, где именно ваша попытка не работает?   -  person Spangen    schedule 11.12.2017
comment
Я думаю, вам нужно создать свою собственную функцию вычисления по тому же принципу, что и Dimitre, ответив здесь для xpath eval: stackoverflow.com/questions/7321553/< /а>   -  person GGO    schedule 11.12.2017
comment
@Spangen Я хотел бы, чтобы результат в столбце «количество» был оцененным выражением выражения, которое находится в XML, но это не работает. (Например, первый столбец должен быть «значение = 1, количество = 1 (поскольку переменная1 = 1), заголовок = Onderdeel1, изображение)   -  person Pecoris    schedule 11.12.2017


Ответы (1)


Если вы используете процессор XSLT, такой как интерпретатор Xalan, который поддерживает функцию EXSLT dyn:evaluate (http://exslt.org/dyn/functions/evaluate/index.html), вы можете использовать

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:dyn="http://exslt.org/dynamic" exclude-result-prefixes="dyn">
<xsl:template match="/">
    <html>
        <head>
            <link rel="stylesheet" href="style.css" type="text/css"/>
        </head>
        <body>
            <xsl:variable name="variable1" select="1" />
            <xsl:variable name="variable2" select="2" />
            <xsl:variable name="variable3" select="3" />

            <div class="np">
                <H2>Parts List</H2>
                <table border ="1">
                    <tr>
                        <th style="width:15%;">ID</th>
                        <th style="width:15%;">Amount</th>
                        <th style="width:40%;">Description</th>
                        <th style="width:30%;">Image</th>
                    </tr>
                    <xsl:for-each select="partslist/part">
                        <tr>
                            <td><xsl:value-of select="@value" /></td>
                            <td><xsl:value-of select="dyn:evaluate(@amount)"/></td>
                            <td><xsl:value-of select="title/nl"/></td>
                            <td><img style="width:100%;" src="{image/@src}"/></td>
                        </tr>
                    </xsl:for-each>
                </table>
            </div>
        </body>
    </html>
</xsl:template>
</xsl:stylesheet>

http://xsltransform.hikmatu.com/948Fn5d.

В зависимости от процессора XSLT, даже если dyn:evaluate не поддерживается, вы можете реализовать эту функциональность с помощью функции расширения.

Или перейдите на процессор XSLT 3, который поддерживает xsl:evaluate:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math" exclude-result-prefixes="xs math"
    version="3.0">

    <xsl:template match="/">
        <html>
            <head>
                <link rel="stylesheet" href="style.css" type="text/css"/>
            </head>
            <body>
                <xsl:variable name="variable1" select="1"/>
                <xsl:variable name="variable2" select="2"/>
                <xsl:variable name="variable3" select="3"/>

                <div class="np">
                    <H2>Parts List</H2>
                    <table border="1">
                        <tr>
                            <th style="width:15%;">ID</th>
                            <th style="width:15%;">Amount</th>
                            <th style="width:40%;">Description</th>
                            <th style="width:30%;">Image</th>
                        </tr>
                        <xsl:for-each select="partslist/part">
                            <tr>
                                <td>
                                    <xsl:value-of select="@value"/>
                                </td>
                                <td>
                                    <xsl:evaluate xpath="@amount" context-item="."
                                        with-params="
                                            map {
                                                xs:QName('variable1'): $variable1,
                                                xs:QName('variable2'): $variable2,
                                                xs:QName('variable3'): $variable3
                                            }"
                                    />
                                </td>
                                <td>
                                    <xsl:value-of select="title/nl"/>
                                </td>
                                <td>
                                    <img style="width:100%;" src="{image/@src}"/>
                                </td>
                            </tr>
                        </xsl:for-each>
                    </table>
                </div>
            </body>
        </html>
    </xsl:template>

</xsl:stylesheet>
person Martin Honnen    schedule 11.12.2017
comment
Спасибо за подробный ответ, одна вещь мне не совсем ясна; В зависимости от процессора XSLT, даже если dyn:evaluate не поддерживается, вы можете реализовать эту функциональность с помощью функции расширения. Как я могу точно реализовать эту функциональность? - person Pecoris; 11.12.2017
comment
Какой именно XSLT-процессор на какой платформе вы используете? Некоторые предоставляют возможность вызова языка программирования или среды, в которой они реализованы, например, XslCompiledTransform может использовать C# или VB.NET для вызова msdn.microsoft.com/en-us/library/. - person Martin Honnen; 11.12.2017
comment
Я действительно использую XslCompiledTransform в С#. Но как мне вызвать метод оценки в этом случае? Заранее спасибо за помощь! - person Pecoris; 11.12.2017
comment
Как правило, чтобы вызвать C# из таблицы стилей XSLT 1, выполненной с помощью XslCompiledTransform, см. docs.microsoft.com/en-us/dotnet/standard/data/xml/. - person Martin Honnen; 11.12.2017
comment
Я не уверен, можно ли вычислить выражение, содержащее переменные, из вашего XSLT, возможно, потребуется тяжелая работа с XsltContext, или это может быть невозможно. Существует еще проект mvpxml.codeplex.com, в котором есть исходный код многих функций EXSLT для XslCompiledTransform, но они не реализуйте там EXSLT dyn:evaluate, только dyn2:evaluate без поддержки переменных. - person Martin Honnen; 11.12.2017
comment
Я не уверен, действительно ли они реализовали свою собственную версию функции расширения evaluate, потому что сложные требования dyn:evaluate EXSLT невозможны с XslCompiledTransform, или авторы этой библиотеки просто не хотели реализовывать версию EXSLT. - person Martin Honnen; 11.12.2017
comment
И было бы возможно, если бы переменные не были «объявлены» в XSLT, но если бы эти переменные были объявлены в моем проекте C#? - person Pecoris; 11.12.2017
comment
Пожалуйста, изучите параметры функции расширения и объектов расширения docs.microsoft.com/en-us/dotnet/standard/data/xml/ я дал ссылку, то я уверен, что вы сами сможете ответить на последний вопрос. - person Martin Honnen; 11.12.2017