【问题标题】:Combine XML element nodes through xslt transformation通过 xslt 转换组合 XML 元素节点
【发布时间】:2013-06-20 08:10:56
【问题描述】:

我需要转换一个 XML,其中转换规则应仅适用于某些元素,其余部分应照原样复制。 以下是源代码块和预期的 xml 块。

<Object class="Item" version="1.0" distName="A-1/B-1/Item-0">
     <p name="sDate">2013-02-11T00:00:00+02:00:00</p>
     <p name="present">1</p>
     <p name="stopD">2013-02-21T00:00:00+02:00:00</p>
     <p name="id">CPU</p>
</Object>
<Object class="Period" version="1.0" distName="A-1/B-1/Item-0/Period-0">
     <p name="sHour">0</p>
     <p name="sMinute">0</p>
     <p name="interval">1</p>
     <p name="day">0</p>
</Object>

<Object class="Items" distName="A-1/B-1/Items-0">
<p name="IsPresent">1</p>
<p name="StartDate">08-11-2012</p>
<p name="StopDate">29-11-2012</p>
<list name="TimePeriod">
    <item>
        <p name="id">1</p>
        <p name="StartTime">00:00</p>
        <p name="day">0</p>
        <p name="interval">15</p>
    </item>
</list>
<list name="TypeRef">
    <p>Diameter</p>
</list>

1. 以上 Object 元素应与另一个基于具有父子层次结构的 distName 的 Object 元素组合。例如:A-1/B-1/Item-0A-1/B-1/Item-0/Period-0

  1. 映射如下:
    • sDate 到 StartDate
    • 呈现给 IsPresent
    • stopD 到 StopDate
    • ID 到 TypeRef 列表
    • 另一个源节点应该映射到时间段列表

谁能帮我解决这个问题?

【问题讨论】:

  • 为了模板的效率... class="Period" 的对象总是出现在 class="Item" 的对象之后还是可以出现在之前?
  • 它可以出现在xml中的任何地方。
  • 嗨@KevinBrown,感谢您的帮助开始......如果单个项目有多个期间,如何处理上述问题。例如:A-1/B-1/Item-0 有 A-1/B-1/Item-0/Period-0 和 A-1/B-1/Item-0/Period-1。如何同时考虑并在 Items 下有多个 TimePeriod 列表?

标签: xslt xslt-1.0


【解决方案1】:

您的预期结果中的某些项目似乎与输入不匹配,但也许这会帮助您从 A 点到 B 点。我没有在这里进行日期转换,我不知道 TypeRef 是什么你的来源。

      <xsl:template match="Object[@class='Item']">
            <xsl:variable name="mainobj" select="."/>
            <xsl:variable name="distName" select="@distName"/>
            <Object class="Items" distName="{$distName}">
                <p name="IsPresent">
                    <xsl:value-of select="p[@name='present']"/>
                </p>
                <p name="StartDate">
                    <xsl:value-of select="p[@name='sDate']"/>
                </p>
                <p name="StopDate">
                    <xsl:value-of select="p[@name='stopD']"/>
                </p>
                <xsl:variable name="objperiod" select="//Object[starts-with(@distName,$distName)][not(.=$mainobj)]"/>
                <xsl:for-each select="$objperiod">
                <list name="TimePeriod">
                    <item>
                        <p name="id">
                            <xsl:value-of select="p[@name='id']"/>
                        </p>

                        <p name="StartTime">
                            <xsl:value-of select="concat(format-number($objperiod/p[@name='sHour'],'00'),':',format-number($objperiod/p[@name='sMinute'],'00'))"/>
                        </p>
                        <p name="day">
                            <xsl:value-of select="$objperiod/p[@name='day']"/>
                        </p>
                        <p name="interval">
                            <xsl:value-of select="$objperiod/p[@name='interval']"/>
                        </p>
                    </item>
                </list>
                </xsl:for-each>
            </Object>
        </xsl:template>  

这会产生以下结果:

   <Object class="Items" distName="A-1/B-1/Item-0">
       <p name="IsPresent">1</p>
       <p name="StartDate">2013-02-11T00:00:00+02:00:00</p>
       <p name="StopDate">2013-02-21T00:00:00+02:00:00</p>
       <list name="TimePeriod">
           <item>
               <p name="id">CPU</p>
               <p name="StartTime">00:00</p>
               <p name="day">0</p>
               <p name="interval">1</p>
           </item>
       </list>
       <list name="TimePeriod">
           <item>
               <p name="id"/>
               <p name="StartTime">00:00</p>
               <p name="day">0</p>
               <p name="interval">1</p>
           </item>
       </list>
       <list name="TimePeriod">
           <item>
               <p name="id"/>
               <p name="StartTime">00:00</p>
               <p name="day">0</p>
               <p name="interval">1</p>
           </item>
       </list>
   </Object>

【讨论】:

  • 嗨@KevinBrown,感谢您的帮助开始......如果单个项目有多个期间,如何处理上述问题。例如:A-1/B-1/Item-0 有 A-1/B-1/Item-0/Period-0 和 A-1/B-1/Item-0/Period-1。如何同时考虑并在 Items 下有多个 TimePeriod 列表?
  • 如果可以有多个,那么变量 objperiod 实际上是一个节点列表。将其移到列表上方并使用 xsl:for-each 迭代每个
  • 我为您编辑了上面的解决方案,为您展示了这个 for-each,这将适用于 1...n TimePeriods。
  • 凯文,非常感谢您对上述主题的帮助。我能够生成理想的 xslt 转换,除了一件事,尽管我有两个 TimePeriod 实例,但它们中的数据是相同的,尽管源不同。在 tat case 中我错过了什么?上面的 [not(.=$mainobj)] 有什么意义?
  • not() 语句是因为匹配是 //Object ... 这意味着它将在自身内部匹配(换句话说,其 class="item" 将在自身内部匹配并创建另一个您也可以通过将变量更改为 ="//Object[@class='Period'][starts-with(@distName,$distName)]"/ 来避免这种情况
猜你喜欢
  • 2011-02-10
  • 1970-01-01
  • 2011-07-20
  • 2017-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-21
相关资源
最近更新 更多