Как передать атрибут xml параметру xslt? - PullRequest
1 голос
/ 18 мая 2011

У меня все работает (спасибо empo), кроме столбца ctrlname. Я не знаю синтаксис достаточно хорошо. То, что я пытаюсь сделать, это использовать xslt для сортировки xml в сетке по имени столбца. Все работает, кроме столбца ctrlname. Как передать атрибут в XSLT? Я пробовал: @name, Data / @ name, Data [@name], ctrlname. Ничего не работает.

    XmlDataSource1.EnableCaching = False
    Dim xslTrnsform As System.Xml.Xsl.XsltArgumentList = New System.Xml.Xsl.XsltArgumentList
    xslTrnsform.AddParam("sortby", "", sortAttr)
    xslTrnsform.AddParam("orderas", "", orderby)
    XmlDataSource1.TransformArgumentList = xslTrnsform
    XmlDataSource1.DataFile = "~/App_LocalResources/DST_Test.xml"
    XmlDataSource1.XPath = "//data"
    XmlDataSource1.TransformFile = xsltFileName
    'XmlDataSource1.DataBind()
    GridView1.DataSource = XmlDataSource1
    GridView1.DataBind()

XSL

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">

    <xsl:param name="sortby"></xsl:param>
    <xsl:param name="orderas"></xsl:param>

    <xsl:output method="xml" indent="yes"/>

    <!--<xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>-->
    <xsl:template match="root">
        <root>
            <xsl:apply-templates select="data">
                <xsl:sort select="*[name()=$sortby]" data-type="text" order="{$orderas}"/>
            </xsl:apply-templates>
        </root>
    </xsl:template>
    <xsl:template match="data">
        <data>
            <xsl:attribute name="ctrlname">
                <xsl:value-of select="@name"/>
            </xsl:attribute>
            <xsl:attribute name="value">
                <xsl:value-of select="value" />
            </xsl:attribute>
            <xsl:attribute name="comment">
                <xsl:value-of select="comment" />
            </xsl:attribute>
        </data>
    </xsl:template>
</xsl:stylesheet>

Ввод XML

<?xml version="1.0" encoding="utf-8" ?>
<root>
    <data name="Test1.Text" xml:space="preserve">
        <value>Please Pick Bare Pump</value>
        <comment>Tab - Pump Configuration</comment>
    </data>
    <data name="Test2.Text" xml:space="preserve">
        <value>Complete</value>
        <comment>A07</comment>
    </data>
    <data name="Test3.Text" xml:space="preserve">
        <value>Confirmed</value>
        <comment>A01</comment>
    </data>
</root>

Ответы [ 3 ]

2 голосов
/ 19 мая 2011

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

Это решение решает проблему (и короче), позволяя указать, должна ли сортировка выполняться по имени атрибута или по имени элемента:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="sortby" select="'attrib!name'"/>
    <xsl:param name="orderas" select="'ascending'"/>
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

    <xsl:template match="root">
        <root>
            <xsl:apply-templates select="data">
                <xsl:sort select=
                "*[name()=substring-after($sortby, 'elem!')]
                |
                 @*[name()=substring-after($sortby, 'attrib!')]"
                data-type="text" order="{$orderas}"/>
            </xsl:apply-templates>
        </root>
    </xsl:template>
    <xsl:template match="data">
        <data ctrlname="{@name}" value="{value}"
              comment="{comment}"/>
    </xsl:template>
</xsl:stylesheet>

При применении к этому документу XML (на основе предоставленного, но сделанного немного более интересным):

<root>
    <data name="Test3.Text" xml:space="preserve">
        <value>Please Pick Bare Pump</value>
        <comment>Tab - Pump Configuration</comment>
        <name>X</name>
    </data>
    <data name="Test2.Text" xml:space="preserve">
        <value>Complete</value>
        <comment>A07</comment>
        <name>Z</name>
    </data>
    <data name="Test1.Text" xml:space="preserve">
        <value>Confirmed</value>
        <comment>A01</comment>
        <name>Y</name>
    </data>
</root>

получен правильный результат (отсортированный по атрибуту name) :

<root>
   <data ctrlname="Test1.Text" value="Confirmed" comment="A01"/>
   <data ctrlname="Test2.Text" value="Complete" comment="A07"/>
   <data ctrlname="Test3.Text" value="Please Pick Bare Pump" comment="Tab - Pump Configuration"/>
</root>

Теперь замените <xsl:param name="sortby" select="'attrib!name'"/> на :

<xsl:param name="sortby" select="'elem!name'"/>

и примените преобразование снова к тому же XML-документу. На этот раз мы получим результат, правильно отсортированный по значениям элемента child- name:

<root>
   <data ctrlname="Test3.Text" value="Please Pick Bare Pump" comment="Tab - Pump Configuration"/>
   <data ctrlname="Test1.Text" value="Confirmed" comment="A01"/>
   <data ctrlname="Test2.Text" value="Complete" comment="A07"/>
</root>

Объяснение

  1. Чтобы различить, хотим ли мы сортировать по элементу-потомку или по атрибуту, мы используем соглашение, согласно которому elem!someName означает, что сортировка должна выполняться по значениям дочернего элемента с именем someName. Аналогично, attrib!someName означает, что сортировка должна выполняться по значениям атрибута с именем someName.

  2. Надпись <xsl:sort> изменяется соответствующим образом для правильного выбора в качестве ключа либо атрибута, либо дочернего элемента. Не допускается двусмысленность, поскольку начальная подстрока параметра sortby теперь однозначно определяет, должен ли ключ быть атрибутом или дочерним элементом.

1 голос
/ 18 мая 2011

Да, извините, я не заметил, что вы хотели также отсортировать по атрибутам. Также обратите внимание, что вы изменили синтаксис xsl:param, и это неверно. Очень важно хранить одинарные кавычки внутри двойных. Вот окончательный шаблон:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">

        <xsl:param name="sortby" select="'value'"/>
        <xsl:param name="orderas" select="'ascending'"/>

    <xsl:output method="xml" indent="yes"/>

    <!--<xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>-->
    <xsl:template match="root">
        <root>
            <xsl:apply-templates select="data">
                <xsl:sort select="*[name()=$sortby]|@*[name()=$sortby]" data-type="text" order="{$orderas}"/>
            </xsl:apply-templates>
        </root>
    </xsl:template>
    <xsl:template match="data">
        <data>
            <xsl:attribute name="ctrlname">
                <xsl:value-of select="@name"/>
            </xsl:attribute>
            <xsl:attribute name="value">
                <xsl:value-of select="value" />
            </xsl:attribute>
            <xsl:attribute name="comment">
                <xsl:value-of select="comment" />
            </xsl:attribute>
        </data>
    </xsl:template>
</xsl:stylesheet>
0 голосов
/ 18 мая 2011

ОК, я думаю, что это должно работать для вас, позволяя вам указывать имена атрибутов или элементов в параметре $ sortby:

<xsl:template match="root">
    <root>
        <xsl:apply-templates select="data">
            <xsl:sort select="*[name()=$sortby] | @*[name()=$sortby]" data-type="text" order="{$orderas}"/>
        </xsl:apply-templates>
    </root>
</xsl:template>

(вы просто передали бы «имя» в качестве значенияпараметр $ sortby)

Проблема заключалась в том, что при выборе узла значения сортировки были только соответствующие элементы (* соответствует только элементам).

...