在XSLT 1.0中的'/'分隔字符串中获取子字符串

时间:2014-08-01 03:04:45

标签: xml xslt xslt-1.0

我将此字符串作为节点的值:

/TAG3/Tag 3 Value/TAG2/Tag2 Value/Tag2 Value 2/Tag 2 value 3/TAG4/Tag4 value/TAG1/Tag 1 value/Tag1 value 2/

如果我需要根据下面的TAG号重新安排

/TAG1/Tag 1 value/Tag1 value 2/TAG2/Tag2 Value/Tag2 Value 2/Tag 2 value 3/TAG3/Tag 3 Value/TAG4/Tag4 value

或通过像这样的标签分解

/TAG1/Tag 1 value/Tag1 value 2/
/TAG2/Tag2 Value/Tag2 Value 2/Tag 2 value 3/
/TAG3/Tag 3 Value/
/TAG4/Tag4 value/

每个字符串应以' /'开头和结尾,并且必须输入关键字(例如' TAG1')和值(例如' Tag1值' )组合,值可以是多个,但关键字必须只有一个

顺便说一句,是否可以在XSLT 1.0中执行此操作?

我有这个输入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>
              <!--Details can come like this format--> 
              <Customer>
                <Name>Customer 1 Name</Name>
                <Address>Address Line 1</Address>
              </Customer>
              <CustomerAcct>
                <AcctName>Account Name 1</AcctName>
                <AcctNumber>12345677</AcctNumber>
              </CustomerAcct>
              <!--Or this-->
              <CustDetails>/CUST/Customer 1 Name/Address Line 1/ACCT/Account Name 1/12345677/BANK/Bank Name/Bank Address/</CustDetails>
            </Parties>
            <AddlInfo>
              <Info1>Info 1</Info1>
              <Info1>Info 2</Info1>
              <Info1>Info 3</Info1>
            </AddlInfo>
          </TransactionDetails>
        </EntryDtls>
      </Entry>
    </Statement>
  </CustomerRecord>
</Document>

对于描述标签CStatement / CStatementLine / Description:

应具有此输出
<?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>
      <!--values below will be coming from 
        <CustDetails>/CUST/Customer 1 Name/Address Line 1/ACCT/Account Name 1/12345677/BANK/Bank Name/Bank Address/</CustDetails> if 
        <Customer>
          <Name>Customer 1 Name</Name>
          <Address>Address Line 1</Address>
        </Customer>
        <CustomerAcct>
          <AcctName>Account Name 1</AcctName>
          <AcctNumber>12345677</AcctNumber>
        </CustomerAcct>
      is not existing-->
      <CustomerName>Customer 1 Name</CustomerName>
      <CustomerAddress>Address Line 1</CustomerAddress>
      <CustAccountName>Account Name</CustAccountName>
      <CustomerBankAccount>12345677</CustomerBankAccount>
      <Description>CUST+Customer 1 Name+Address Line 2+ACCT+Account Name 1+12345677+ADDL+Info 1+Info 2+Info 3</Description>
    </CStatementLine>
  </CStatement>
</Root>

感谢所有帮助:)

1 个答案:

答案 0 :(得分:1)

我担心这可能太复杂了,无法在论坛答案的范围内轻松回答。不过,我相信这里解决了三个主要问题:

  1. 从给定字符串中提取值;而
  2. 为每个值分配标签;和
  3. 对结果值进行排序
  4. 可以显示。

    鉴于以下测试输入

    <input>
        <CustDetails>/ACCT/Account Name 1/12345677/BANK/Bank Name/Bank Address/CUST/Customer 1 Name/Address Line 1/</CustDetails>
    </input>
    

    以下样式表:

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exsl="http://exslt.org/common"
    extension-element-prefixes="exsl">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*" />
    
    <xsl:variable name="tags" select="'|CUST|BANK|ACCT|'"/>
    
    <xsl:template match="input">
        <!-- first pass -->
        <xsl:variable name="values">
            <xsl:call-template name="tokenize">
                <!-- remove the opening slash -->
                <xsl:with-param name="text" select="substring(CustDetails, 2, string-length(CustDetails))"/>
            </xsl:call-template>
        </xsl:variable>
        <!-- output -->
        <output>
            <xsl:for-each select="exsl:node-set($values)/value">
                <!-- sort by position of @tag in $tags -->
                <xsl:sort select="string-length(substring-before($tags, concat('|', @tag, '|')))" data-type="number" order="ascending"/>
                    <xsl:copy-of select="."/>
            </xsl:for-each>
        </output>
    </xsl:template>
    
    <xsl:template name="tokenize">
        <xsl:param name="text"/>
        <xsl:param name="delimiter" select="'/'"/>
        <xsl:param name="tag"/>
        <xsl:if test="$text">
            <xsl:variable name="token" select="substring-before($text, $delimiter)"/>
            <xsl:choose>
                <xsl:when test="contains($tags, concat('|', $token, '|'))">
                    <!-- new tag -->
                    <value tag="{$token}">
                        <xsl:value-of select="$token"/>
                    </value>
                     <!-- recursive call -->              
                    <xsl:call-template name="tokenize">
                        <xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
                        <xsl:with-param name="tag" select="$token"/>
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <value tag="{$tag}">
                        <xsl:value-of select="$token"/>
                    </value>
                     <!-- recursive call -->
                    <xsl:call-template name="tokenize">
                        <xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
                        <xsl:with-param name="tag" select="$tag"/>
                    </xsl:call-template>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:if>
    </xsl:template>
    
    </xsl:stylesheet>
    

    将返回:

    <?xml version="1.0" encoding="UTF-8"?>
    <output>
      <value tag="CUST">CUST</value>
      <value tag="CUST">Customer 1 Name</value>
      <value tag="CUST">Address Line 1</value>
      <value tag="BANK">BANK</value>
      <value tag="BANK">Bank Name</value>
      <value tag="BANK">Bank Address</value>
      <value tag="ACCT">ACCT</value>
      <value tag="ACCT">Account Name 1</value>
      <value tag="ACCT">12345677</value>
    </output>
    

    您只需要修改输出,而不是按原样复制值,将其放在文本字符串中。