XSLT:如何将串联字符串用作xsl:for-each select的变量名?

时间:2019-07-26 10:07:19

标签: xslt foreach concatenation xslt-1.0

我正在一个系统迁移项目中,我的任务是从系统A接收SOAP XML请求,然后将请求中的6个参数名称转换为系统B可读的新名称,并输出一个参数已更改。 (所有参数名称均已更改)

请求:

<q0:Command>
 <q0:Transaction>
  <q0:Operation namespace="Provisioning" name="Create" modifier="Data">
   <q0:ParameterList>
    <q0:StringParameter name="Action">Create</q0:StringParameter>
    <q0:StructParameter name="Create">
     <q0:StringParameter name="UserID">1234567X</q0:StringParameter>
     <q0:StringParameter name="Device1">abcd567890</q0:StringParameter>
     <q0:StringParameter name="Contract1">Postpaid</q0:StringParameter>
     <q0:StringParameter name="Line1">990108024011900</q0:StringParameter>
     <q0:StringParameter name="Device2">efgh567890</q0:StringParameter>
     <q0:StringParameter name="Contract2">Postpaid</q0:StringParameter>
     <q0:StringParameter name="Line2">990104562499105</q0:StringParameter>
    </q0:StructParameter>
   </q0:ParameterList>
  </q0:Operation>
 </q0:Transaction>
</q0:Command>

首先,我只是在每个选择块中使用新名称手动重新创建了每个参数,然后它起作用了。情况是,现在有一个要求,即不应该将值一一地硬编码,而应该在循环中检查(以防万一每个用户的设备数量增加)。

~~所以我想到了声明一个$ LoopIndex变量,并将其连接到与参数名称匹配的字符串,例如:~~

因此,我将下面蒂姆的答案实施到了我的for-each部分中,就像这样:

<xsl:for-each select="//q0:CommandRequestData/q0:Command/q0:Transaction/q0:Operation/q0:ParameterList/q0:StructParameter[@name='Create']">
 <xsl:for-each select="q0:StringParameter">
  <xsl:choose>
   <xsl:when test="@name = 'UserID'">
    <ins:Parameter name="USER_ID" value="{string()}" />
   </xsl:when>
   <xsl:when test="starts-with(@name, 'Device')">
    <ins:Parameter name="concat('DEVICE_ID_', substring(., 7))" value="{string()}" />
   </xsl:when>
   <xsl:when test="starts-with(@name, 'Contract')">
    <ins:Parameter name="concat('CONTRACT_TYPE_', substring(., 9))" value="{string()}" />
   </xsl:when>
   <xsl:when test="starts-with(@name, 'Line')">
    <ins:Parameter name="concat('LINE_ID_', substring(., 5))" value="{string()}" />
   </xsl:when>
  </xsl:choose>
 </xsl:for-each>
</xsl:for-each>

~~上面的代码不起作用。当我说“ @ name = concat('Device',$ LoopIndex)”时,页面无法理解我的意思是“ @ name ='Device1'”。 XSLT可能发生这种情况吗?还是我需要坚持对参数分配进行硬编码?~~

不幸的是,这只是半成功。该页面实际上是将“ concat('DEVICE_ID_',substring(。,7))”作为参数名称的字符串,而不是执行串联。

传递给系统B的结果SOAP XML请求看起来像这样:

<q0:Command>
 <q0:Transaction>
  <q0:Operation namespace="Provisioning" name="Create" modifier="Data">
   <q0:ParameterList>
    <q0:StringParameter name="Action">Create</q0:StringParameter>
    <q0:StructParameter name="Create">
     <ins:Parameter name="USER_ID" value="1234567X"/>
     <ins:Parameter name="concat('DEVICE_ID_', substring(., 5))" value="abcd567890"/>
     <ins:Parameter name="concat('CONTRACT_TYPE_', substring(., 13))" value="Postpaid"/>
     <ins:Parameter name="concat('IMSI_', substring(., 5))" value="990108024011900"/>
     <ins:Parameter name="concat('DEVICE_ID_', substring(., 5))" value="efgh567890"/>
     <ins:Parameter name="concat('CONTRACT_TYPE_', substring(., 13))" value="Postpaid"/>
     <ins:Parameter name="concat('IMSI_', substring(., 5))" value="990104562499105"/>
    </q0:StructParameter>
   </q0:ParameterList>
  </q0:Operation>
 </q0:Transaction>
</q0:Command>

1 个答案:

答案 0 :(得分:1)

我将在此处使用属性上的模板匹配以及身份模板,而不是xsl:for-eachxsl:choose,只是为了使代码更整洁(尽管不一定要解决您的问题, )。

但是要解决您的问题,您可以使用字符串函数从@name属性中提取当前数字。

尝试使用此XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:q0="q0" >
  <xsl:output method="xml" indent="yes"/>

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

  <xsl:template match="q0:StructParameter[@name='Create']/q0:StringParameter/@name">
    <xsl:attribute name="name">
      <xsl:choose>
        <xsl:when test=". = 'UserID'">
          <xsl:text>USER_ID</xsl:text>
        </xsl:when>
        <xsl:when test="starts-with(., 'Device')">
          <xsl:value-of select="concat('DEVICE_ID_', substring(., 7))" />
        </xsl:when>
        <xsl:when test="starts-with(., 'Contract')">
          <xsl:value-of select="concat('CONTRACT_TYPE_', substring(., 9))" />
        </xsl:when>
        <xsl:when test="starts-with(., 'Line')">
          <xsl:value-of select="concat('LINE_ID_', substring(., 5))" />
        </xsl:when>
        <xsl:otherwise>NA</xsl:otherwise>
      </xsl:choose>
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

请注意,您必须为q0更改名称空间URI,以相应地匹配您的实际名称空间。