XSL:计算XSL 1.0中的前面元素

时间:2014-10-17 16:58:19

标签: xslt xpath

我正在生成以下XML(此处显示的片段):

<ns1:OBX>
  <ns1:OBX.1>2</ns1:OBX.1>
  <ns1:OBX.2>CE</ns1:OBX.2>
  <ns1:OBX.3>
     <ns1:CE_OBS.1>
        <ns1:CM_OBS.1>aaa</ns1:CM_OBS.1>
     </ns1:CE_OBS.1>
  </ns1:OBX.3>
  <ns1:OBX.5>
     <ns1:CE.1>N</ns1:CE.1>
  </ns1:OBX.5>
</ns1:OBX>
<ns1:OBX>
  <ns1:OBX.1>2</ns1:OBX.1>
  <ns1:OBX.2>DT</ns1:OBX.2>
  <ns1:OBX.3>
     <ns1:CE_OBS.1>
        <ns1:CM_OBS.1>bbb</ns1:CM_OBS.1>
     </ns1:CE_OBS.1>
  </ns1:OBX.3>
  <ns1:OBX.5>
     <ns1:CE.1>20011231</ns1:CE.1>
  </ns1:OBX.5>
</ns1:OBX>

我正在尝试使用OBX段的序列号填充ns1:OBX.1(这些节点中可能有大约15-25个)。在XSL中,我在每个OBX映射中添加:

<ns1:OBX>
  <ns1:OBX.1>
    <xsl:value-of select='count("preceding:://ns1:OBX")+1'/>
  </ns1:OBX.1>
 ........

然而,这总是产生2的值。你能告诉我这里有什么问题吗?

在这里包含更多样式表:

<xsl:template match="/">
<ns1:ADT_A01>
  <xsl:attribute name="Standard">
    <xsl:text disable-output-escaping="no">HL7</xsl:text>
  </xsl:attribute>
  <xsl:attribute name="Version">
    <xsl:text disable-output-escaping="no">2.3</xsl:text>
  </xsl:attribute>
   ...........   
   ........... 
  <xsl:for-each select="/inp1:XXXProfileMsg/inp1:XXXProfileData/inp1:exStayIndicator">
    <ns1:OBX>
      <ns1:OBX.1>
        <xsl:number/>
      </ns1:OBX.1>
      <ns1:OBX.2>
        <xsl:text disable-output-escaping="no">CE</xsl:text>
      </ns1:OBX.2>
      <ns1:OBX.3>
        <ns1:CE_OBS.1>
          <ns1:CM_OBS.1>
            <xsl:text disable-output-escaping="no">aaa</xsl:text>
          </ns1:CM_OBS.1>
        </ns1:CE_OBS.1>
      </ns1:OBX.3>
      <ns1:OBX.5>
        <ns1:CE.1>
          <xsl:value-of select="."/>
        </ns1:CE.1>
      </ns1:OBX.5>
    </ns1:OBX>
  </xsl:for-each>
  <xsl:for-each select="/inp1:XXXProfileMsg/inp1:XXXProfileData/inp1:exStayDate">
    <xsl:if test=".">
      <ns1:OBX>
        <ns1:OBX.1>
            <xsl:number/>
        </ns1:OBX.1>
        <ns1:OBX.2>
          <xsl:text disable-output-escaping="no">DT</xsl:text>
        </ns1:OBX.2>
        <ns1:OBX.3>
          <ns1:CE_OBS.1>
            <ns1:CM_OBS.1>
              <xsl:text disable-output-escaping="no">bbb</xsl:text>
            </ns1:CM_OBS.1>
          </ns1:CE_OBS.1>
        </ns1:OBX.3>
        <ns1:OBX.5>
          <ns1:CE.1>
            <xsl:value-of select='xp20:format-dateTime(.,"[Y0001][M01][D01]")'/>
          </ns1:CE.1>
        </ns1:OBX.5>
      </ns1:OBX>
    </xsl:if>
  </xsl:for-each>
  <xsl:for-each select="/inp1:XXXProfileMsg/inp1:XXXProfileData/inp1:releaseType">
    <ns1:OBX>
       <ns1:OBX.1>
          <xsl:value-of select='count(preceding::ns1:OBX) + 1'/>
        </ns1:OBX.1>
      <ns1:OBX.2>
        <xsl:text disable-output-escaping="no">CE</xsl:text>
      </ns1:OBX.2>
      <ns1:OBX.3>
        <ns1:CE_OBS.1>
          <ns1:CM_OBS.1>
            <xsl:text disable-output-escaping="no">reltyp</xsl:text>
          </ns1:CM_OBS.1>
        </ns1:CE_OBS.1>
      </ns1:OBX.3>
      <ns1:OBX.5>
        <ns1:CE.1>
          <xsl:value-of select="."/>
        </ns1:CE.1>
      </ns1:OBX.5>
    </ns1:OBX>
  </xsl:for-each>
  ............
  ............
</ns1:ADT_A01>

1 个答案:

答案 0 :(得分:0)

我的原始答案指出了发布的xsl-valueof元素中存在的问题。评论最终发现提问者想要计算生成的节点,这些节点与输入节点没有明确的先验序列关系。所以......

原始模板远比它需要的多得多,但这不是我关注的问题。如果从输入文档转换节点的方式是以与相应输入节点不同的顺序生成结果节点,那么我看到的最佳解决方案是执行两次传递。但是,您可以在同一个XSLT运行中执行此操作,方法是将第一个传递的结果收集到临时文档(片段)中,然后对其进行转换。

这样的事情:

<xsl:variable name='obx-nodes'>
  <xsl:for-each select="/inp1:XXXProfileMsg/inp1:XXXProfileData/inp1:exStayIndicator">
    <ns1:OBX>
    <ns1:OBX.1/>
    <ns1:OBX.2>
      <xsl:text disable-output-escaping="no">CE</xsl:text>
    </ns1:OBX.2>
  ...
  </xsl:for-each>
  <xsl:for-each select="/inp1:XXXProfileMsg/inp1:XXXProfileData/inp1:exStayDate">
    <xsl:if test=".">
      <ns1:OBX>
      <ns1:OBX.1/>
      <ns1:OBX.2>
        <xsl:text disable-output-escaping="no">DT</xsl:text>
      </ns1:OBX.2>
      ...
    </xsl:if>
  </xsl:for-each>
  ...
</xsl:variable>

<xsl:apply-templates select='$obx-nodes' />

将与其他几个模板配对:

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

<xsl:template match='ns1:OBX.1'>
  <ns1:OBX.1>
    <xsl:value-of select='count(preceding::ns1:OBX)'/>
  </ns1:OBX1>
</xsl:template>