此处不能使用轴步子::元素('':PRODUCT_LIST):上下文项是原子值

时间:2015-02-10 11:04:20

标签: xslt xslt-2.0

提前感谢您的支持。

我有以下xml和xslt

<SUBSCRIBER>
    <PRODUCT_LIST>
        <PRODUCT_INFO>
            <ID>BA3</ID>
            <PRODUCT_TYPE>Chargeable Bonus Product</PRODUCT_TYPE>
            <NSN1>34178</NSN1>
            <NSN2>2015-02-18 23:59:59</NSN2>
            <OFFER>1104</OFFER>
            <DA_UNIT>time</DA_UNIT>
            <UA>1003</UA>
        </PRODUCT_INFO>
        <PRODUCT_INFO>
            <ID>SID15</ID>
            <PRODUCT_TYPE>Rate Cutter</PRODUCT_TYPE>
            <NSN1>2015-12-23</NSN1>
            <OFFER>1215</OFFER>
        </PRODUCT_INFO>
        <PRODUCT_INFO>
            <ID>UseRs325GetRs25</ID>
            <PRODUCT_TYPE>Usage Subscription- Traffic</PRODUCT_TYPE>
            <NSN1>0</NSN1>
            <NSN2>2015-02-15</NSN2>
            <NSN3>2015-02-05</NSN3>
            <NSN4>2015-02-15 14:01:33</NSN4>
            <OFFER>1250</OFFER>
            <UA>1095</UA>
            <UA2>1096</UA2>
            <THRESHOLD>325</THRESHOLD>
            <UA_INTERVAL>10</UA_INTERVAL>
        </PRODUCT_INFO>
    </PRODUCT_LIST>
</SUBSCRIBER>

XSLT:

<xsl:template match="SUBSCRIBER">

    <xsl:variable name="PRODUCT_TYPE" select="PRODUCT_LIST/PRODUCT_INFO[(PRODUCT_TYPE eq 'Chargeable Bonus Product') or (PRODUCT_TYPE eq 'Home Zone') or (PRODUCT_TYPE eq 'Usage Subscription- Traffic') or (PRODUCT_TYPE eq 'Telescopic Charging') or (PRODUCT_TYPE eq 'Usage Subscription- Recharge')]/PRODUCT_TYPE"/>
    <xsl:for-each select="1 to count($PRODUCT_TYPE)">
        <xsl:variable name="index" select="."/>
        <xsl:variable name="product_name" select="$PRODUCT_TYPE[$index]"/>
        <xsl:value-of select="PRODUCT_LIST/PRODUCT_INFO[(PRODUCT_TYPE eq $product_name)]/UA"/>
    </xsl:for-each>

</xsl:template>

我收到以下异常,

描述:此处不能使用轴步子::元素(&#39;&#39;:PRODUCT_LIST):上下文项是原子值

请告知修复。

3 个答案:

答案 0 :(得分:2)

错误消息说明了一切 - 当你在for-each 1 to count($PRODUCT_TYPE)内时,上下文项(.)是一个数字而不是一个节点,所以你不能使用一个亲戚value-of中的XPath。您需要将for-each外部的上下文项保存在另一个变量中,然后使用相对于该路径的路径:

<xsl:variable name="dot" select="."/><!-- . here is the SUBSCRIBER -->
<xsl:for-each select="1 to count($PRODUCT_TYPE)">
    <xsl:variable name="index" select="."/><!-- . here is the number -->
    <xsl:variable name="product_name" select="$PRODUCT_TYPE[$index]"/>
    <xsl:value-of select="$dot/PRODUCT_LIST/PRODUCT_INFO[(PRODUCT_TYPE eq $product_name)]/UA"/>
</xsl:for-each>

虽然正如其他答案所指出的那样,从长远来看,您可以更好地重构代码以使用更标准的XSLT处理方式,而不是简单地尝试移植您熟悉的for(int i = 0; i < arr.length; i++)之类的结构更多命令式编程语言。是的,需要一段时间才能习惯更具功能性的思维方式,但从长远来看,它会带来更简单,更易于维护的代码。

答案 1 :(得分:0)

为什么不改变:

<xsl:for-each select="1 to count($PRODUCT_TYPE)">

<xsl:for-each select="$PRODUCT_TYPE">

然后您将处于<PRODUCT_TYPE>的上下文中,您只需要:

<xsl:value-of select="../UA"/>

直接获取兄弟<UA>值,而不是那么详细地说明你所做的事情。


更简单的是将第一个变量定义为:

<xsl:variable name="PRODUCT_INFO" select="PRODUCT_LIST/PRODUCT_INFO[(PRODUCT_TYPE eq 'Chargeable Bonus Product') or (PRODUCT_TYPE eq 'Home Zone') or (PRODUCT_TYPE eq 'Usage Subscription- Traffic') or (PRODUCT_TYPE eq 'Telescopic Charging') or (PRODUCT_TYPE eq 'Usage Subscription- Recharge')]"/>

然后在:

<xsl:for-each select="$PRODUCT_INFO">

达到:

<xsl:value-of select="UA"/>

答案 2 :(得分:0)

你真的不需要这里的任何变数

<xsl:template match="SUBSCRIBER">
    <!-- filter on PRODUCT_LIST/PRODUCT_INFO/PRODUCT_TYPE -->
    <xsl:apply-templates select="PRODUCT_LIST/PRODUCT_INFO[(PRODUCT_TYPE eq 'Chargeable Bonus Product') or (PRODUCT_TYPE eq 'Home Zone') or (PRODUCT_TYPE eq 'Usage Subscription- Traffic') or (PRODUCT_TYPE eq 'Telescopic Charging') or (PRODUCT_TYPE eq 'Usage Subscription- Recharge')]"/>
</xsl:template>

<xsl:template match="PRODUCT_INFO">
    <!-- Get relevant PRODUCT_INFO values -->
    <xsl:value-of select="UA"/>
</xsl:template>