XPath如何动态创建属性的路径

时间:2017-06-14 23:05:52

标签: xml xslt xpath xslt-1.0

我正在创建一个表格,其中标题名称来自标题元素,数据来自 reportdata 属性元素。但是,我不知道属性的名称: Value1,Value2,ect .. 提前。生成属性的名称并将其存储到 FieldName 属性中,该属性位于 reportnode 内的元素内。

我无法找到一种方法来制作使用生成的 FieldNames 的XPath,并从 reportdata 获取相应属性的值。有任何想法吗?或者这是不可能的。

以下是XML:

<report>
    <reportparameters>
        <header Order="1" HeaderName="Day_1" />
        <header Order="2" HeaderName="Day_2" />
        <header Order="3" HeaderName="Day_3" />
        <header Order="4" HeaderName="Total" />

        <reportnode ColumnCount="4">
            <column Order="1" FieldName="Value1" />
            <column Order="2" FieldName="Value2" />
            <column Order="3" FieldName="Value3" />
            <column Order="4" FieldName="TotalValue" />
        </reportnode>
    </reportparameters>

    <reportdata Value1="0" Value2="0" Value3="0" TotalValue="0"/>
    <reportdata Value1="0" Value2="0" Value3="0" TotalValue="0"/>
    <reportdata Value1="0" Value2="0" Value3="0" TotalValue="0"/>
    <reportdata Value1="0" Value2="0" Value3="0" TotalValue="0"/>
    <reportdata Value1="0" Value2="0" Value3="0" TotalValue="0"/>
</report>

XSL尝试:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="no"/>
    <xsl:template match="/">
        <report>       
            <row>
                <xsl:for-each select="/report/reportparameters/header">
                    <xsl:variable name="columnCounter" select="position()"/>
                    <xsl:element name="{./@HeaderName}">
                    <xsl:for-each select="/report/reportdata">
                        <xsl:value-of select="@{../reportparameters/reportnode/column[@Order=$columnCounter+1]/@FieldName}"/>
                    </xsl:for-each>
                    </xsl:element>
                </xsl:for-each>
            </row>
        </report>
    </xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:2)

我怀疑你可以做到:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/report">
    <xsl:variable name="cols" select="reportparameters/reportnode/column" />
    <report> 
        <xsl:for-each select="reportdata">
            <row>
                <xsl:for-each select="@*">
                    <xsl:variable name="i" select="position()"/>
                    <xsl:element name="{$cols[$i]/@FieldName}">
                        <xsl:value-of select="."/>
                    </xsl:element>
                </xsl:for-each>
            </row>
        </xsl:for-each>
    </report>
</xsl:template>

</xsl:stylesheet>

得到:

<?xml version="1.0" encoding="UTF-8"?>
<report>
  <row>
    <Value1>0</Value1>
    <Value2>0</Value2>
    <Value3>0</Value3>
    <TotalValue>0</TotalValue>
  </row>
  <row>
    <Value1>0</Value1>
    <Value2>0</Value2>
    <Value3>0</Value3>
    <TotalValue>0</TotalValue>
  </row>
  <row>
    <Value1>0</Value1>
    <Value2>0</Value2>
    <Value3>0</Value3>
    <TotalValue>0</TotalValue>
  </row>
  <row>
    <Value1>0</Value1>
    <Value2>0</Value2>
    <Value3>0</Value3>
    <TotalValue>0</TotalValue>
  </row>
  <row>
    <Value1>0</Value1>
    <Value2>0</Value2>
    <Value3>0</Value3>
    <TotalValue>0</TotalValue>
  </row>
</report>

这假设每个reportdata具有相同的属性,顺序相同,与column中的reportnode元素的顺序相对应。否则会稍微复杂一点。

OTOH,如果 - 如您的示例所示 - reportdata的属性具有所需的名称,它可以更简单:

<xsl:template match="/report">
    <report> 
        <xsl:for-each select="reportdata">
            <row>
                <xsl:for-each select="@*">
                    <xsl:element name="{name()}">
                        <xsl:value-of select="."/>
                    </xsl:element>
                </xsl:for-each>
            </row>
        </xsl:for-each>
    </report>
</xsl:template>