【问题标题】:Looping thru XSLT通过 XSLT 循环
【发布时间】:2014-07-31 03:28:47
【问题描述】:

我有这个输入 XML:

<?xml version='1.0' encoding='UTF-8'?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn-sample">
  <CustomerRecord>
    <Statement>
      <StmtId>123</StmtId>
      <StmtDate>2013-08-16</StmtDate>
      <AcctNumber>123456789</AcctNumber>
      <Balance>
        <Type>OP</Type>
        <Amount>1.00</Amount>
        <CreditOrDebit>DR</CreditOrDebit>
        <Date>2013-08-15</Date>
      </Balance>
      <Balance>
        <Type>CL</Type>
        <Amount>2.00</Amount>
        <CreditOrDebit>CR</CreditOrDebit>
        <Date>2013-08-16</Date>
      </Balance>
      <Balance>
        <Type>FW</Type>
        <Amount>3.00</Amount>
        <CreditOrDebit>CR</CreditOrDebit>
        <Date>2013-08-17</Date>
      </Balance>
      <Entry>
        <Amount>7778.70</Amount>
        <CreditOrDebit>DR</CreditOrDebit>
        <EntryDtls>
          <TransactionDetails>
            <Parties>
              <Customer>
                <Name>Customer 1 Name</Name>
                <Address>Address Line 1</Address>
              </Customer>
              <CustomerAcct>
                <AcctName>Account Name 1</AcctName>
                <AcctNumber>12345677</AcctNumber>
              </CustomerAcct>
            </Parties>
            <AddlInfo>
              <Info1>Info 1</Info1>
              <Info1>Info 2</Info1>
              <Info1>Info 3</Info1>
            </AddlInfo>
          </TransactionDetails>
        </EntryDtls>
      </Entry>
      <Entry>
        <Amount>5555.70</Amount>
        <CreditOrDebit>DR</CreditOrDebit>
        <EntryDtls>
          <TransactionDetails>
            <Parties>
              <Customer>
                <Name>Customer 2 Name</Name>
                <Address>Address Line 2</Address>
              </Customer>
              <CustomerAcct>
                <AcctName>Account Name 2</AcctName>
                <AcctNumber>12345678</AcctNumber>
              </CustomerAcct>
            </Parties>
            <AddlInfo>
              <Info1>Info 1</Info1>
              <Info1>Info 2</Info1>
            </AddlInfo>
          </TransactionDetails>
        </EntryDtls>
      </Entry>
    </Statement>
    <Statement>
      <StmtId>124</StmtId>
      <StmtDate>2013-08-18</StmtDate>
      <AcctNumber>123456780</AcctNumber>
      <Balance>
        <Type>OP</Type>
        <Amount>4.00</Amount>
        <CreditOrDebit>CR</CreditOrDebit>
        <Date>2013-08-15</Date>
      </Balance>
      <Balance>
        <Type>CL</Type>
        <Amount>5.00</Amount>
        <CreditOrDebit>DR</CreditOrDebit>
        <Date>2013-08-16</Date>
      </Balance>
      <Balance>
        <Type>FW</Type>
        <Amount>6.00</Amount>
        <CreditOrDebit>CR</CreditOrDebit>
        <Date>2013-08-17</Date>
      </Balance>
      <Entry>
        <Amount>7777.70</Amount>
        <CreditOrDebit>DR</CreditOrDebit>
        <EntryDtls>
          <TransactionDetails>
            <Parties>
              <Customer>
                <Name>Customer 3 Name</Name>
                <Address>Address Line 3</Address>
              </Customer>
              <CustomerAcct>
                <AcctName>Account Name 3</AcctName>
                <AcctNumber>12345679</AcctNumber>
              </CustomerAcct>
            </Parties>
            <AddlInfo>
              <Info1>Info 1</Info1>
              <Info1>Info 2</Info1>
              <Info1>Info 3</Info1>
            </AddlInfo>
          </TransactionDetails>
        </EntryDtls>
      </Entry>
    </Statement>
  </CustomerRecord>
</Document>

然后我有这个 XSLT:

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

  <xsl:template match="/urn:Document">
    <Root>
      <xsl:apply-templates select="/urn:Document/urn:CustomerRecord/urn:Statement" />
    </Root>
  </xsl:template>

  <xsl:template match="/urn:Document/urn:CustomerRecord/urn:Statement">
    <CStatement>
      <CStatementId>
        <xsl:value-of select="/urn:Document/urn:CustomerRecord/urn:Statement/urn:StmtId" />
      </CStatementId>
      <CStatementDate>
        <xsl:choose>
          <xsl:when test ="/urn:Document/urn:CustomerRecord/urn:Statement/urn:StmtDate!=''">
            <xsl:value-of select="/urn:Document/urn:CustomerRecord/urn:Statement/urn:StmtDate" />
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="/urn:Document/urn:CustomerRecord/urn:Statement/urn:Balance[contains('|CL|FW|', concat('|', urn:Type, '|'))]/urn:Date" />
          </xsl:otherwise>
        </xsl:choose>
      </CStatementDate>
      <AccountNumber>
        <xsl:if test="/urn:Document/urn:CustomerRecord/urn:Statement/urn:AcctNumber!=''">
          <xsl:value-of select ="/urn:Document/urn:CustomerRecord/urn:Statement/urn:AcctNumber"/>
        </xsl:if>
      </AccountNumber>
      <OpeningBalance>
        <xsl:choose>
          <xsl:when test="/urn:Document/urn:CustomerRecord/urn:Statement/urn:Balance[contains('|OP|PR|', concat('|', urn:Type, '|'))]/urn:CdtDbtInd='DR'">
            <xsl:value-of select="format-number(/urn:Document/urn:CustomerRecord/urn:Statement/urn:Balance[contains('|OP|PR|', concat('|', urn:Type, '|'))]/urn:Amount * -1, '#.00')" />
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="format-number(/urn:Document/urn:CustomerRecord/urn:Statement/urn:Balance[contains('|OP|PR|', concat('|', urn:Type, '|'))]/urn:Amount, '#.00')" />
          </xsl:otherwise>
        </xsl:choose>
      </OpeningBalance>
      <ClosingBalance>
        <xsl:choose>
          <xsl:when test="/urn:Document/urn:CustomerRecord/urn:Statement/urn:Balance[contains('|CL|FW|', concat('|', urn:Type, '|'))]/urn:CdtDbtInd='DR'">
            <xsl:value-of select="format-number(/urn:Document/urn:CustomerRecord/urn:Statement/urn:Balance[contains('|CL|FW|', concat('|', urn:Type, '|'))]/urn:Amount * -1, '#.00')" />
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="format-number(/urn:Document/urn:CustomerRecord/urn:Statement/urn:Balance[contains('|CL|FW|', concat('|', urn:Type, '|'))]/urn:Amount, '#.00')" />
          </xsl:otherwise>
        </xsl:choose>
      </ClosingBalance>
      <xsl:apply-templates select="/urn:Document/urn:CustomerRecord/urn:Statement/urn:Entry" />
    </CStatement>
  </xsl:template>

  <xsl:template match="/urn:Document/urn:CustomerRecord/urn:Statement/urn:Entry">
    <StatementLine>
      <DebitOrCredit>
        <xsl:value-of select ="/urn:Document/urn:CustomerRecord/urn:Statement/urn:Entry/urn:CreditOrDebit"/>
      </DebitOrCredit>
      <Amount>
        <xsl:choose>
          <xsl:when test="/urn:Document/urn:CustomerRecord/urn:Statement/urn:Entry/urn:CreditOrDebit='DR'">
            <xsl:value-of select="format-number(/urn:Document/urn:CustomerRecord/urn:Statement/urn:Entry/urn:Amount * -1, '#.00')" />
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="format-number(/urn:Document/urn:CustomerRecord/urn:Statement/urn:Entry/urn:Amount, '#.00')" />
          </xsl:otherwise>
        </xsl:choose>
      </Amount>
      <CustomerName>
        <xsl:value-of select="/urn:Document/urn:CustomerRecord/urn:Statement/urn:Entry/urn:EntryDtls/urn:TransactionDetails/urn:Parties/urn:Customer/urn:Name" />
        <!--NtryDtls/TransactionDetails/Parties/Dbtr/Nm-->
      </CustomerName>
      <CustomerBankAccount>
        <xsl:value-of select="/urn:Document/urn:CustomerRecord/urn:Statement/urn:Entry/urn:EntryDtls/urn:TransactionDetails/urn:Parties/urn:CustomerAcct/urn:AcctNumber" />
      </CustomerBankAccount>
      <Description>


      </Description>
    </StatementLine>
  </xsl:template>
</xsl:stylesheet>

应该有这个输出:

<?xml version="1.0" encoding="utf-8"?>
<Root> <!--should have no attribute-->
  <CStatement>
    <CStatementId>123</CStatementId>
    <CStatementDate>2013-08-16</CStatementDate>
    <AccountNumber>123456789</AccountNumber>
    <OpeningBalance>-1.00</OpeningBalance>
    <ClosingBalance>2.00</ClosingBalance>
    <CStatementLine>
      <DebitOrCredit>DR</DebitOrCredit>
      <Amount>-7778.70</Amount>
      <CustomerName>Customer 1 Name</CustomerName>
      <CustomerBankAccount>12345677</CustomerBankAccount>
      <Description></Description>
    </CStatementLine>
    <StatementLine>
      <DebitOrCredit>DR</DebitOrCredit>
      <Amount>5555.70</Amount>
      <CustomerName>Customer 2 Name</CustomerName>
      <CustomerBankAccount>12345678</CustomerBankAccount>
      <Description></Description>
    </StatementLine>
  </CStatement>
  <CStatement>
    <CStatementId>124</CStatementId>
    <CStatementDate>2013-08-18</CStatementDate>
    <AccountNumber>123456780</AccountNumber>
    <OpeningBalance>4.00</OpeningBalance>
    <ClosingBalance>-5.00</ClosingBalance>
    <CStatementLine>
      <DebitOrCredit>DR</DebitOrCredit>
      <Amount>7777.70</Amount>
      <CustomerName>Customer 3 Name</CustomerName>
      <CustomerBankAccount>12345679</CustomerBankAccount>
      <Description></Description>
    </CStatementLine>
  </CStatement>
</Root>

我的 XSLT 有两个问题: 1 它只获取 Statement 或 StatementLines 的第一个值,如下所示:

<Root xmlns:urn="urn-sample">
  <CStatement>
    <CStatementId>123</CStatementId>
    <CStatementDate>2013-08-16</CStatementDate>
    <AccountNumber>123456789</AccountNumber>
    <OpeningBalance>1.00</OpeningBalance>
    <ClosingBalance>2.00</ClosingBalance>
    <StatementLine>
      <DebitOrCredit>DR</DebitOrCredit>
      <Amount>-7778.70</Amount>
      <CustomerName>Customer 1 Name</CustomerName>
      <CustomerBankAccount>12345677</CustomerBankAccount>
      <Description />
    </StatementLine>
    <StatementLine>
      <DebitOrCredit>DR</DebitOrCredit>
      <Amount>-7778.70</Amount>
      <CustomerName>Customer 1 Name</CustomerName>
      <CustomerBankAccount>12345677</CustomerBankAccount>
      <Description />
    </StatementLine>
    <StatementLine>
      <DebitOrCredit>DR</DebitOrCredit>
      <Amount>-7778.70</Amount>
      <CustomerName>Customer 1 Name</CustomerName>
      <CustomerBankAccount>12345677</CustomerBankAccount>
      <Description />
    </StatementLine>
  </CStatement>
  <CStatement>
    <CStatementId>123</CStatementId>
    <CStatementDate>2013-08-16</CStatementDate>
    <AccountNumber>123456789</AccountNumber>
    <OpeningBalance>1.00</OpeningBalance>
    <ClosingBalance>2.00</ClosingBalance>
    <StatementLine>
      <DebitOrCredit>DR</DebitOrCredit>
      <Amount>-7778.70</Amount>
      <CustomerName>Customer 1 Name</CustomerName>
      <CustomerBankAccount>12345677</CustomerBankAccount>
      <Description />
    </StatementLine>
    <StatementLine>
      <DebitOrCredit>DR</DebitOrCredit>
      <Amount>-7778.70</Amount>
      <CustomerName>Customer 1 Name</CustomerName>
      <CustomerBankAccount>12345677</CustomerBankAccount>
      <Description />
    </StatementLine>
    <StatementLine>
      <DebitOrCredit>DR</DebitOrCredit>
      <Amount>-7778.70</Amount>
      <CustomerName>Customer 1 Name</CustomerName>
      <CustomerBankAccount>12345677</CustomerBankAccount>
      <Description />
    </StatementLine>
  </CStatement>
</Root>

2 最后,我不确定如何使用变量或任何函数来存储满足此要求的 Description 标记的值:

  • 一个。连接字符串 'CUST' + Customer/Name + Customer/Address
  • 乙。连接字符串 'ACCT' + CustomerAcct/AcctName + > CustomerAcct/AcctNumber
  • c。连接 AddlInfo/Info1 下的任何值
  • 连接 a+b+c .... 等

我希望有人可以帮助我解决这个问题。谢谢大家

顺便说一句,我在 XSLT 1.0 上需要它

【问题讨论】:

  • 请将所有代码减少到重现问题所需的最低限度。每条 10 行是理想的。很可能在解决问题的过程中,您会自己找到根本原因。

标签: xml xslt xslt-1.0


【解决方案1】:

您的基本错误是您使用的是绝对路径而不是相对路径。比较这两个最小化样式表的结果:

XSLT 1.0(绝对)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
                xmlns:urn="urn-sample">
<xsl:strip-space elements="*" />
<xsl:output indent="yes" omit-xml-declaration="yes" />

<xsl:template match="/urn:Document">
    <Root>
        <xsl:apply-templates select="/urn:Document/urn:CustomerRecord/urn:Statement" />
    </Root>
</xsl:template>

<xsl:template match="/urn:Document/urn:CustomerRecord/urn:Statement">
    <CStatement>
        <CStatementId>
            <xsl:value-of select="/urn:Document/urn:CustomerRecord/urn:Statement/urn:StmtId" />
        </CStatementId>
    </CStatement>
</xsl:template>

</xsl:stylesheet>

XSLT 1.0(相对)

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

<xsl:template match="/urn:Document">
    <Root>
        <xsl:apply-templates select="urn:CustomerRecord/urn:Statement" />
    </Root>
</xsl:template>

<xsl:template match="urn:Statement">
    <CStatement>
        <CStatementId>
            <xsl:value-of select="urn:StmtId" />
        </CStatementId>
    </CStatement>
</xsl:template>

</xsl:stylesheet>

在第一个例子中,指令:

<xsl:value-of select="/urn:Document/urn:CustomerRecord/urn:Statement/urn:StmtId" />

从根开始,始终获取first语句的Id值,无论当前循环正在处理哪个语句。

【讨论】:

  • 这正是我要找的。现在对第二个有什么想法吗?
  • @zyberjock 我建议您发布一个单独的问题,因为这两个问题无关。 Stack Overflow 是一种公共资源 - 将每个问题限制为一个问题有助于读者浏览它以找到解决自己问题的方法。
  • 好的,谢谢,在这里问了另一个问题stackoverflow.com/questions/25052304/…
猜你喜欢
  • 1970-01-01
  • 2017-11-22
  • 2020-09-04
  • 2017-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多