当前位置: 首页 > 知识库问答 >
问题:

XSLT2.0:根据for each-group的当前索引评估和修改元素值

穆单鹗
2023-03-14

我试图评估EndDate作为下一个开始日期-1(下一个开始日期的前一天)。下面给出的是输入XML:

<?xml version="1.0" encoding="UTF-8"?>
<queryCompoundEmployeeResponse>
   <CompoundEmployee>
         <id>176</id>
         <person>
               <action>NO CHANGE</action>
               <person_id_external>10005005</person_id_external>
               <personal_information>
                     <end_date>9999-12-31</end_date>
                     <start_date>2021-06-03</start_date>
               </personal_information>
               <personal_information>
                     <end_date>2021-06-02</end_date>
                     <start_date>2017-12-06</start_date>
               </personal_information>
               <phone_information>
                     <phone_type>B</phone_type>
               </phone_information>
               <phone_information>
                     <phone_number>7CAED430A494B3C404</phone_number>
               </phone_information>
               <email_information>
                     <last_modified_on>2019-03-25T02:44:51.000Z</last_modified_on>
               </email_information>
               <employment_information>
                     <start_date>2017-12-06</start_date>
                     <user_id>10005005</user_id>
                     <job_information>
                           <end_date>9999-12-31</end_date>
                           <start_date>2019-03-02</start_date>
                        </job_information>
               </employment_information>
         </person>
         <execution_timestamp>2021-07-14T15:08:38.000Z</execution_timestamp>
         <version_id>2105P0</version_id>
      <Start_Dates>
         <StartDate>2017-12-06</StartDate>
         <StartDate>2017-12-06</StartDate>
         <StartDate>2019-03-02</StartDate>
         <StartDate>2021-06-03</StartDate>
      </Start_Dates>
      <End_Dates>
         <EndDate>2021-06-02</EndDate>
         <EndDate>NA</EndDate>
         <EndDate>9999-12-31</EndDate>
         <EndDate>9999-12-31</EndDate>
      </End_Dates>
   </CompoundEmployee>
   </queryCompoundEmployeeResponse>

电流输出:

    <?xml version="1.0" encoding="UTF-8"?>
<queryCompoundEmployeeResponse xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <CompoundEmployee>
      <Person>
         <StartDate>2017-12-06</StartDate>
         <EndDate>2019-03-01</EndDate>
      </Person>
      <Person>
         <StartDate>2019-03-02</StartDate>
         <EndDate/>
      </Person>
      <Person>
         <StartDate>2021-06-03</StartDate>
         <EndDate>9999-12-31</EndDate>
      </Person>
   </CompoundEmployee>
</queryCompoundEmployeeResponse>

所需输出:

<?xml version="1.0" encoding="UTF-8"?>
<queryCompoundEmployeeResponse xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <CompoundEmployee>
      <Person>
         <StartDate>2017-12-06</StartDate>
         <EndDate>2019-03-01</EndDate>
      </Person>
      <Person>
         <StartDate>2019-03-02</StartDate>
         <EndDate>2021-06-02</EndDate>
      </Person>
      <Person>
         <StartDate>2021-06-03</StartDate>
         <EndDate>9999-12-31</EndDate>
      </Person>
   </CompoundEmployee>
</queryCompoundEmployeeResponse>

我试图计算每个Person节点的EndDate为一天减去下一个StartDate。对于最后一个人,EndDate应该是输入XML中的最后一个EndDate。

以下是我试图增强的代码:

<xsl:template match="/queryCompoundEmployeeResponse">
    <queryCompoundEmployeeResponse>
        <xsl:for-each select="CompoundEmployee">
            <xsl:copy>
                <xsl:variable name="person" select="person" />
                <xsl:for-each-group select="Start_Dates/StartDate" group-by=".">
                    <Person>
                       <xsl:copy-of select="."/>
                       
                        <!--Start of EndDate logic for last record-->
                        <xsl:variable name="nxtStartDate" select="following-sibling::StartDate"/>
                           <xsl:if test="not($nxtStartDate)">
                             <xsl:variable name="i" select="position()"/>
                                <EndDate>
                                    <xsl:value-of select="../following-sibling::End_Dates/EndDate[last()]"/>   
                                </EndDate>
                           </xsl:if>
                          <!-- End of EndDate logic for last record-->  
                          
                          <!--Calculate next start date -1 -->
                            <xsl:if test="$nxtStartDate">
                            <xsl:variable name="currentDate" select="Start_Dates/StartDate"/>
                            <xsl:variable name="i" select="position()"/>
                            <EndDate>
                                <xsl:apply-templates select="following-sibling::StartDate[$i+1]"/>
                            </EndDate>
                            </xsl:if>
                      <!--Calculate next start date -1 -->
                    
                     <!-- //Some additional required code://
                     
                       <xsl:copy-of select="$person/* except $person/(personal_information | phone_information | email_information | employment_information)"/>
                       <xsl:copy-of select="$person/personal_information[start_date le current() and current() le end_date]"/>
                       <xsl:copy-of select="$person/employment_information[start_date le current() and current() le end_date]"/>
                        <xsl:copy-of select="$person/employment_information/job_information[start_date le current() and current() le end_date]"/> 
                     -->
                    </Person>
                </xsl:for-each-group>
            </xsl:copy>
        </xsl:for-each>
    </queryCompoundEmployeeResponse>
</xsl:template>

<xsl:template match="StartDate">
 <xsl:variable name="sDate" select="." as="xs:date"/>
        <xsl:copy-of select="$sDate - 1*xs:dayTimeDuration('P1D')"/>
</xsl:template>
    
</xsl:stylesheet>



 I need something like following-sibling::(.)[index+1]. It gives me the End date in first Person. But next one is still empty. 

我做错了什么?另外,我如何修改这个为每个部分都有单独的模板?

提前谢谢!

共有1个答案

公冶子琪
2023-03-14

当您执行xsl:for each group时,您将被置于组中第一项的上下文中。在此上下文中,表达式following sibling::StartDate选择原始XML文档中组的第一个StartDate的以下同级,而不是当前组中的同级。当然,你不能使用任何一个轴来到达下一组的第一个项目——这是你真正想要的。

或许可以这样尝试:

XSLT2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:template match="/queryCompoundEmployeeResponse">
    <queryCompoundEmployeeResponse>
        <xsl:for-each select="CompoundEmployee">
            <xsl:copy>
            
                <xsl:variable name="start-dates">
                    <xsl:for-each-group select="Start_Dates/StartDate" group-by=".">
                        <xsl:copy-of select="."/>
                    </xsl:for-each-group>
                </xsl:variable>
            
                <xsl:for-each select="$start-dates/StartDate">
                    <Person>
                        <xsl:copy-of select="."/>
                        <xsl:variable name="next" select="following-sibling::StartDate[1]"/>   
                        <EndDate>
                            <xsl:value-of select="if ($next) then xs:date($next) - xs:dayTimeDuration('P1D') else '9999-12-31'"/>   
                         </EndDate>
                    </Person>
                </xsl:for-each>
                
            </xsl:copy>
        </xsl:for-each>
    </queryCompoundEmployeeResponse>
</xsl:template>

</xsl:stylesheet>

注:这是一个快速草案;它可能会被简化一点-可能会沿着以下路线:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:template match="/queryCompoundEmployeeResponse">
    <queryCompoundEmployeeResponse>
        <xsl:for-each select="CompoundEmployee">
            <xsl:copy>
                <xsl:variable name="start-dates" select="distinct-values(Start_Dates/StartDate)"/>
                <xsl:for-each select="$start-dates">
                    <Person>
                        <StartDate>
                            <xsl:value-of select="."/>   
                        </StartDate>
                        <xsl:variable name="i" select="position()"/>   
                        <EndDate>                       
                            <xsl:value-of select="if ($i != last()) then xs:date($start-dates[$i+ 1]) - xs:dayTimeDuration('P1D') else '9999-12-31'"/>
                        </EndDate>
                    </Person>
                </xsl:for-each>
            </xsl:copy>
        </xsl:for-each>
    </queryCompoundEmployeeResponse>
</xsl:template>

</xsl:stylesheet>
 类似资料:
  • 我有一份我正在处理的项目清单。我正在寻找初始列表中的特定项目,并希望在遍历列表时从该列表中删除已找到的项目。我遍历列表使用 有没有一种方法可以在不操纵两个列表的情况下做到这一点?

  • 我想了解Selenium是如何评估页面的。 基于这个测试,PhantomJS如何评估页面是令人困惑的。我一直认为它会检查DOM,但对于元素文本,它会基于可见性进行评估!

  • 问题内容: 我想知道是否可以编辑循环中正在处理的当前对象 我正在处理一系列对象,我想遍历数据库中查找与该问题对象相关的答案。因此,对于每一个问题去获取答案对象,并更新当前 里面 我的循环,这样我可以输出/别处过程。 问题答案: 有两种方法 这样可以保存密钥,因此您可以在主变量中再次对其进行更新 要么 添加会保持更新。但我想说,即使这样比较短,也建议使用第一个(请参阅Paystey的评论) 根据PH

  • 问题内容: 假设我有 有没有一种有效的numpy方法来查找值变化的每个索引?例如,我想要一些结果, 如果某些numpy例程无法做到这一点,那么在python中执行此操作的快速方法是什么?推荐给一些很好的numpy教程对我来说也很有用,因为我是个numpy初学者。 问题答案: 您可以通过将每个元素与其相邻元素进行比较来以numpy的形式获得此功能; 要获取索引,请使用“ where”功能 在这里,您

  • 我认为我对Flink窗口的理解可能是错误的,因为它们没有像我期望的那样从文档或Flink书中进行评估。目标是将具有相当静态数据的Kafka主题与具有不断传入数据的Kafka主题连接起来。 返回FlinkKafkaConsumer 是我的键选择器的占位符。 我的关键问题: 这里到底发生了什么?是否在窗口完成处理后发出记录?我希望有一个实时输出到水槽,但这将解释很多。 与此相关的是:我可以用onEle

  • 主要内容:基本语法,删除索引删除索引是指将表中已经存在的索引删除掉。不用的索引建议进行删除,因为它们会降低表的更新速度,影响数据库的性能。对于这样的索引,应该将其删除。 在 MySQL 中修改索引可以通过删除原索引,再根据需要创建一个同名的索引,从而实现修改索引的操作。 基本语法 当不再需要索引时,可以使用 DROP INDEX 语句或 ALTER TABLE 语句来对索引进行删除。 1) 使用 DROP INDEX 语句