XSLT - 动态添加元素

Posted

技术标签:

【中文标题】XSLT - 动态添加元素【英文标题】:XSLT - Adding Elements dynamically 【发布时间】:2010-11-30 12:40:58 【问题描述】:

我需要以表格形式显示某些 XML 内容(用于 pdf 报告的 XSL-FO), 并且并非所有要显示的列都存在于源 XML 中。所以,我想知道 如果有一种方法可以通过嵌入额外的列来转换源 XML 某些元素值,然后处理生成的 XML 以显示内容?

例如,对于源数据:

约翰·多伊开发角色> 100会员> 保罗编码员开发角色> 40会员> 亨利泰斯特qa角色> 80会员> 彼得测试员qa角色> 40会员> 项目团队>

我希望数据显示为:

姓名 角色 开发 QA -------------------------- John Doe 开发 100 保罗编码器开发 40 亨利测试仪 qa 80 彼得测试员 QA 40 -------------------------- 角色总数:140 120 --------------------------

我想知道我是否可以使用类似的东西:

元素>

这样我就可以在运行时嵌入元素 100 等等 第一次通过,然后使用生成的 XML 显示新列“dev”的数据 和'qa',这样,计算每种角色类型的总数会更简单 (例如,dev 列的“sum(preceding-sibling::member/dev)”),以及每个的数据 'dev' 和 'qa' 列中的单元格可以分别是这些标签的值。

使用以下样式表(页面格式 省略细节以保持简短),但我不相信这是恰当的解决方案。

... 角色总数:调用模板> 调用模板> ... 模板>

【问题讨论】:

【参考方案1】:

如果添加了除开发人员和 QA 之外的更多工作角色,会发生什么情况?你的样式表能应付吗?也许您可以利用 Muenchian Grouping 来获取样式表中所有可能的角色,然后为每个可能的角色动态生成列?

<xsl:key name="roles" match="role" use="."/>

<xsl:template match="/projectteam">
 <table border="1">
  <tr>
   <td>Name</td>
   <td>Role</td>
   <xsl:for-each select="member[generate-id(role) = generate-id(key('roles', role)[1])]">
    <td>
     <xsl:value-of select="role"/>
    </td>
   </xsl:for-each>
  </tr>
  <xsl:apply-templates select="member"/>
 </table>
</xsl:template>

<xsl:template match="member">
 <xsl:variable name="currentrole" select="role"/>
 <xsl:variable name="currenthrs" select="hrs"/>
 <tr>
  <td>
   <xsl:value-of select="name"/>
  </td>
  <td>
   <xsl:value-of select="role"/>
  </td>
  <xsl:for-each select="/projectteam/member[generate-id(role) = generate-id(key('roles', role)[1])]">
   <td>
    <xsl:choose>
     <xsl:when test="$currentrole = role">
      <xsl:value-of select="$currenthrs"/>
     </xsl:when>
    </xsl:choose>
   </td>
  </xsl:for-each>
 </tr>
</xsl:template>

我输出的是 html,而不是 XSL-FO,但也许这会给你大致的想法。

【讨论】:

谢谢!!我试过了,效果很好!这真的是一个很好的通用解决方案!现在我知道了“generate0id()”和关键元素的一些用例!我已经固定了一组类似列的“角色”(尽管有 11 个),所以这种方法会大大减少代码,但是再次动态地引入 11 个新元素会使最后对它们进行总计变得容易得多。我将尝试这种方法和多通道样式表(使用 node-set()),看看哪个更有意义。谢谢【参考方案2】:

是的,你可以。

回答你的问题。确实,我还没有阅读过庞大的样式表。

【讨论】:

你能建议怎么做吗?我尝试了各种组合,但没有任何效果。我遇到的真正问题有点复杂,即我有一个可以有多个容器的邮件元素,每个容器都可以有多个捆绑包。每个捆绑包都有一个特定的 LevelType,并且有一个描述 TotalPieces 的元素。因此,要显示每个 buldle 的 TotalPieces,在其 LevelType 的列中显示它有点棘手,并且在底部显示每个 levelType 的总数变得更加混乱。这是我非常怀念添加新元素的能力的地方(即 LevelType w/value 设置为 TotalPieces)。谢谢 就像你说的那样:&lt;xsl:element name="role" /&gt;(在你的例子中当然是member)。我以为你没试过。究竟什么不适合你,也不适合说什么? 好吧,我添加了一个新模板:
 <xsl:template match="member"> <xsl:element name="role"> <xsl:value-的 select="hrs"/> <xsl:apply-templates select="member"/> </xsl:element> </xsl:template> 
并尝试在成员的现有模板,但它不起作用(尽管我仍然不清楚模板)我尝试在成员的现有模板中添加这些行:
 <xsl:element name="role"> &lt ;xsl:value-of select="hrs"/> </xsl:element> 
我得到的只是来自 FOP 的关于未知格式对象的警告。
第二次尝试:(prev. post 搞砸了) 1. 2.(从现有的成员模板中): 两者都不起作用 但是 fop 不应该识别&lt;dev/&gt; 元素。我宁愿一步一步解决问题。首先,您需要为 fop 生成输入,并查看它是否是您想要的。将您的想法建立在您仅根据 fop 的消息生成的 xml 上对我来说听起来是错误的。

以上是关于XSLT - 动态添加元素的主要内容,如果未能解决你的问题,请参考以下文章

XSLT:将命名空间添加到根元素

XSLT 将命名空间前缀添加到元素最佳实践

xslt 1.0 添加新元素

XSLT 如何组合模板并将现有字段添加到某些元素

如何将前缀类型添加到重复父节点并使用 XSLT 选择每个元素的所有元素?

XSLT 1.0 添加元素增量 ID