用于解析2个XML文档的XSLT

时间:2015-01-08 17:29:28

标签: xml xslt

我有这个肥皂答案文件,来自财务部门。

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soap:Body>
        <RequestRecordAsXmlResponse xmlns="http://xml.thomson.com/financial/v1/tools/distribution/dataworks/enterprise/2003-07/">
            <RequestRecordAsXmlResult>
                <Record>
                    <Source>Datastream</Source>
                    <Instrument>TOTMKEU</Instrument>
                    <StatusType>Connected</StatusType>
                    <StatusCode>0</StatusCode>
                    <StatusMessage/>
                    <Fields>
                        <CCY>U$</CCY>
                        <DATE>
                            <Item>2014-01-06T00:00:00</Item>
                            <Item>2014-01-07T00:00:00</Item>
                            <Item>2014-01-08T00:00:00</Item>
                            <Item>2014-01-09T00:00:00</Item>
                            <Item>2014-01-10T00:00:00</Item>

                        </DATE>
                        <DISPNAME>EU-DS Market</DISPNAME>
                        <FREQUENCY>D</FREQUENCY>
                        <P>
                            <Item>1740.46</Item>
                            <Item>1749.02</Item>
                            <Item>1749.66</Item>
                            <Item>1742.87</Item>
                            <Item>1761.12</Item>
                        </P>
                        <SYMBOL>TOTMKEU</SYMBOL>
                    </Fields>
                </Record>
            </RequestRecordAsXmlResult>
        </RequestRecordAsXmlResponse>
    </soap:Body>
</soap:Envelope>

我想创建xml输出:

<results>
  <result>
    <tmstp>2014-01-07T00:00:00</tmstp>
    <val>1740.46</val>
  </result>
  <result>
    <tmstp>2014-01-08T00:00:00</tmstp>
    <val>1749.02</val>
  </result> etc ...

我尝试了很多东西,但未能完全做到。 我只能处理两个节点中的一个(DATE或P),而不是两个节点。

我最后的尝试是迭代节点DATE以获取日期(Item)然后使用position()函数以获取节点P中的相应项目。像这样:

<xslt:stylesheet xmlns:xslt="http://www.w3.org/1999/XSL/Transform" xmlns:csw-xform="http://www.compositesw.com/2003/xform" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://xml.thomson.com/financial/v1/tools/distribution/dataworks/enterprise/2003-07/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
  <xslt:template match="/">
    <xslt:variable name="_tmstp"/>
    <xslt:variable name="_val"/>
    <xslt:element name="results">
      <xslt:for-each select="soap-env:Envelope/soap-env:Body/ns1:RequestRecordAsXmlResponse/ns1:RequestRecordAsXmlResult/ns1:Record/ns1:Fields">
        <xslt:for-each select="ns1:DATE">
          <xslt:for-each select="ns1:Item">
            <xslt:variable name="_tmstp" select="."/>
            <xslt:variable name="_val" select="soap-env:Envelope/soap-env:Body/ns1:RequestRecordAsXmlResponse/ns1:RequestRecordAsXmlResult/ns1:Record/ns1:Fields/ns1:P/ns1:Item[position()]"/>
            <xslt:element name="result">
              <xslt:element name="tmstp">
                <xslt:value-of select="$_tmstp"/>
              </xslt:element>
              <xslt:element name="val">
                <xslt:value-of select="$_val"/>
              </xslt:element>
            </xslt:element>
          </xslt:for-each>
        </xslt:for-each>
      </xslt:for-each>
    </xslt:element>
  </xslt:template>
</xslt:stylesheet>

但它失败了。 我也使用了xslt“循环”,但没有太大的成功:“tmstp”值没问题,但“val”(第二个节点= P)仍为空。

你可以帮忙吗? 经过大量的研究,试验和错误,我坚持这件事我感觉很简单,但今天肯定比我强。

非常感谢 文森特

2 个答案:

答案 0 :(得分:0)

你在正确的路线上,但你的相对路径是错误的,而且你不能直接在方括号中使用position(),因为你在不同的上下文中得到不同的位置值。尝试更多像

<xslt:variable name="_tmstp" select="."/>
<xslt:variable name="_pos" select="position()" />
<xslt:variable name="_val" select="../../ns1:P/ns1:Item[$_pos]"/>

_val路径相对于您当前正在查看的Item元素,因此我们只需向上两级(包含Fields元素)然后返回两级再次向下(到Item内的相应P。)

一些旁白:

  • XSLT样式表中使用的常规前缀是xsl:而不是xslt:,如果您想要从示例中复制片段,那么如果您坚持通常的约定就会容易得多
  • 当元素名称是静态已知时,您不需要使用xsl:element,只需使用文字结果元素
<tmstp><xslt:value-of select="$_tmstp"/></tmstp>
<val><xslt:value-of select="$_val"/></val>

答案 1 :(得分:0)

完整的代码。

感谢旁白,我会尽快用你的意见刷新代码。

<xslt:stylesheet xmlns:xslt="http://www.w3.org/1999/XSL/Transform" xmlns:csw-xform="http://www.compositesw.com/2003/xform" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://xml.thomson.com/financial/v1/tools/distribution/dataworks/enterprise/2003-07/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
  <xslt:template match="/">
    <xslt:variable name="_tmstp"/>
    <xslt:variable name="_val"/>
    <xslt:element name="results">
      <xslt:for-each select="soap-env:Envelope/soap-env:Body/ns1:RequestRecordAsXmlResponse/ns1:RequestRecordAsXmlResult/ns1:Record/ns1:Fields">
        <xslt:for-each select="ns1:DATE">
          <xslt:for-each select="ns1:Item">
            <xslt:variable name="_tmstp" select="."/>
            <xslt:variable name="_pos" select="position()"/>
            <xslt:variable name="_val" select="../../ns1:P/ns1:Item[$_pos]"/>
            <xslt:element name="result">
              <xslt:element name="tmstp">
                <xslt:value-of select="$_tmstp"/>
              </xslt:element>
              <xslt:element name="val">
                <xslt:value-of select="$_val"/>
              </xslt:element>
            </xslt:element>
          </xslt:for-each>
        </xslt:for-each>
      </xslt:for-each>
    </xslt:element>
  </xslt:template>
</xslt:stylesheet>