【问题标题】:flat xml to hierarchial xml with extra content平面 xml 到具有额外内容的分层 xml
【发布时间】:2016-12-10 13:53:35
【问题描述】:

我只是 xslt 领域的新手。由于我正在努力完成以下工作,我希望有人可以帮助我解决这个问题。

我有一个平面输入 xml 文件,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<data>
   <Date>31-07-2016</Date>
   <Document_Date>31-07-2016</Document_Date>
   <ReportDate>31-07-2016</ReportDate>
   <Description>Some description</Description>
   <GLAccount_code>1234</GLAccount_code>
   <Costcenter_code>ALG</Costcenter_code>
   <Debtor_code>123456</Debtor_code>
   <Project_code>123456789</Project_code>
   <Currency_Code>EUR</Currency_Code>
   <Debit>0</Debit>
   <Credit>234.561386342626</Credit>
   <FreeText_number>WIP</FreeText_number>
 <!-- notice that here starts A new Date  (this repeats about 50 times with other data) -->
   <Date>31-07-2016</Date>
   <Document_Date>31-07-2016</Document_Date>
 <!-- and so on like above till FreeText_number -->
   <FreeText_number>WIP</FreeText_number>
</data>

我想要的 XML 输出应该是这样的:

<FinEntries>
    <FinEntry entry="20160804">
        <Division code="010" />
        <FinPeriod number="8"/>
        <Journal code="8600" type="M">
            <Journal_Description>Memoriaal OHW</Journal_Description>
        </Journal>
        <FinEntryLine number="1" type="N" subtype="N" code="   2" linecode="B" transactiontype="100">
            <Date>2016-07-31</Date>   <!-- Should come from data/Date -->
            <FinReferences TransactionOrigin="N">
                <DocumentDate>2016-07-31</DocumentDate> <!-- Should come from data/
                <ReportDate>2016-07-31</ReportDate>  <!-- Should come from data/ReportDate -->
            </FinReferences>    
            <GLAccount code="8090"> <!--Should come from GLAccount_code-->
            </GLAccount>
            <Description>OHW: WIP Change</Description>

            <Costcenter code="ALG">
            </Costcenter> <!-- Should come from Costcenter_code -->

            <Debtor code="9904" number = "9904" type="C">   <!-- Should come from Debtor_code -->

            </Debtor>
            <Project code="2550661-2" type="I" status="A"> <!-- Should come from Project_code (only the code ofcourse) -->
            </Project>
            <Amount>
                <Currency code="EUR"/>EUR</curremcy>   <!-- Should come from Currency_Code --> 
                <Debit>0</Debit>  <!-- Should come from Debit -->
                <Credit>-0.01</Credit> <!--Should come from Credit -->
            </Amount>
            <FreeFields>
                <FreeTexts>
                    <FreeText number="1">WIP</FreeText>  <!-- should come from FreeText_number -->
                </FreeTexts>
            </FreeFields>
        </FinEntryLine>

<!-- From here it will start a new FinEntryLine using the next set of data of the input xml again starting with a FinEntryLine-->
        <FinEntryLine number="1" type="N" subtype="N" code="   2" linecode="B" transactiontype="100">
            <Date>2016-07-31</Date>
<!-- and so on till it covered the whole input xml-->
    </FinEntry>
</FinEtnries>

我尝试了几天来完成这项工作,但我似乎没有让我的 xslt 按我想要的方式工作。这就是我现在拥有的:

     <FinEntries>
       <FinEntry entry="20163107">
       <Division code="010"></Division>
       <FinYear number="2016"></FinYear>
       <FinPeriod number="7"></FinPeriod>
       <Journal code="86" type="M">
         <Description>Memoriaal OHW</Description>
       </Journal>
       <Amount>
         <Currency code="EUR"></Currency>
       </Amount>
                     <xsl:copy>
              <FinEntryLine number="1" type="N" subtype="N" code="   2" linecode="B" transactiontype="100">
                 <xsl:apply-templates select="/*" />  
              </FinEntryLine>
                     </xsl:copy>
         </FinEntry>
     </FinEntries>



 </xsl:template>

       <xsl:template match="Date">
         <date>
           <xsl:value-of select="."/>
         </date>
       </xsl:template>

       <xsl:template match="Document_Date">
         <FinReferences TransactionOrigin="N">
         <DocumentDate>
           <xsl:value-of select="."/>
         </DocumentDate>
         <ReportDate>
           <xsl:value-of select="."/>
         </ReportDate>    
         </FinReferences>             
       </xsl:template>

       <xsl:template match="GLAccount_code">
          <xsl:element name="GLAccount">
             <xsl:attribute name="code"><xsl:value-of select="."/></xsl:attribute>
          </xsl:element>
       </xsl:template>

       <xsl:template match="Description">
         <Description>
           <xsl:value-of select="."/>
         </Description>
       </xsl:template>

       <xsl:template match="Costcenter_code">
          <xsl:element name="Costcenter">
             <xsl:attribute name="code"><xsl:value-of select="."/></xsl:attribute>
          </xsl:element>
       </xsl:template>

       <xsl:template match="Debtor_code">
          <xsl:element name="Debtor">
             <xsl:attribute name="code"><xsl:value-of select="."/></xsl:attribute>
             <xsl:attribute name="number">Some number</xsl:attribute>
             <xsl:attribute name="type">Some type</xsl:attribute>
          </xsl:element>
       </xsl:template>

       <xsl:template match="Project_code">
          <xsl:element name="Project">
             <xsl:attribute name="code"><xsl:value-of select="."/></xsl:attribute>
             <xsl:attribute name="type">Some type</xsl:attribute>
             <xsl:attribute name="status">Some status</xsl:attribute>
          </xsl:element>
       </xsl:template>

       <xsl:template match="Currency_Code or Debit or Credit">
          <xsl:element name="Amount">
             <xsl:element name="Currency"> <xsl:value-of select="Currency_Code"/>
             </xsl:element>
             <xsl:element name="Debit"> <xsl:value-of select="Debit"/>
             </xsl:element>
             <xsl:element name="Credit"> <xsl:value-of select="Credit"/>
             </xsl:element>            
          </xsl:element>
       </xsl:template>

       <xsl:template match="FreeText_number">
          <xsl:element name="FreeFields">
             <xsl:element name="FreeTexts"> 
               <xsl:element name="FreeText">
               <xsl:attribute name="number"><xsl:value-of select="."/></xsl:attribute>
               </xsl:element>
             </xsl:element>            
          </xsl:element>
       </xsl:template>

 </xsl:stylesheet>      

结果中缺少:

  • 在 xslt 找到新的 Date 节点后,我的 FinEntryLine 不会停止并以新的 FinEntryLine 重新开始。
  • 货币、借方和贷方存在缺失值,因此借方和贷方金额低于金额。

附加信息:我的处理器无法处理 xslt 2.0

提前非常感谢您。 我希望有人有时间帮助我解决这个问题(甚至可以告诉我我做错了什么)。

【问题讨论】:

    标签: xml xslt xslt-1.0 hierarchy flat-file


    【解决方案1】:

    为了尽量减少将元素分组的问题,每个组都以Date 元素开头,请考虑以下样式表:

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:key name="grp" match="*[not(self::Date)]" use="generate-id(preceding-sibling::Date[1])" />
    
    <xsl:template match="/data">
        <FinEntry>
            <Division/>
            <FinPeriod/>
            <Journal>
                <Journal_Description></Journal_Description>
            </Journal>
            <FinEntries>
                <xsl:for-each select="Date">
                    <FinEntryLine>
                        <Date>
                            <xsl:value-of select="."/>
                        </Date>
                        <xsl:apply-templates select="key('grp', generate-id())" /> 
                    </FinEntryLine>
                </xsl:for-each>
            </FinEntries>
        </FinEntry>
    </xsl:template>
    
    <!-- add more templates here -->
    
    </xsl:stylesheet> 
    

    【讨论】:

    • 不错的分组逻辑。
    • 感谢您的快速回复。我对生成 ID 不是很熟悉。但我仍然遇到 2 个问题 第一个模板
    • 我建议您发布有关这些(以及任何其他)问题的单独问题。 -- 提示:你不能在匹配模式中使用or;如果您希望同一个模板匹配多个节点,请使用 | 联合运算符。
    • 非常感谢迈克尔。我为我的第二个问题搜索了多个示例。因此,我不需要问另一个问题。两者的解决方案是使用 |在以下模板中匹配并指定 Currencycode、借方、贷方的确切位置。
    猜你喜欢
    • 1970-01-01
    • 2012-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多