XSLT 2.0 - 使用分组来嵌套元素
我正在开发一个样式表,它从几乎没有任何内容的输入文件以分层格式输出。每个部分都有一个非常平坦的层次结构,因此我一直在使用向我建议的分组方法 - 它按第一个节点名称对每个集合进行分组,从而从平坦的部分中形成一个很好的层次结构。这种方法效果很好 - 我只需要修改它以考虑我想要跳过的元素。
示例输入文件(注意:每个部分有多个 Header 元素):
<Root>
<VolumeName>Volume 1 </VolumeName>
<Section>
<SectionName> Section1 </SectionName>
<Title> Title1 </Title>
<Header> NameOfDocument1 </Header>
<Header> Header1 </Header>
<Sub1> Sub1 first </Sub1>
<Sub1> Sub1 second </Sub1>
<Sub2> Sub2 first, Sub1 second </Sub2>
<Sub1> Sub1 third </Sub1>
<Sub2> Sub2 first, Sub1 third </Sub2>
</Section>
<Section>
<SectionName> Section2 </SectionName>
<Title> Title2 </Title>
<Header> Header2 </Header>
<Sub1> Sub1 first </Sub1>
<Sub1> Sub1 second </Sub1>
<Sub2> Sub2 first, Sub1 second </Sub2>
<Sub1> Sub1 third </Sub1>
<Sub2> Sub2 first, Sub1 third </Sub2>
</Section>
</Root>
示例输入代码的输出应如下所示:
<Volume1>
<Section1 Number="Section1" Name="NameOfDocument1" Title="Title1">
<Header1>
<Step>
Sub1 first
</Step>
<Step>
Sub1 second
<Step>
Sub2 first, Sub1 second
</Step>
</Step>
<Step>
Sub1 third
<Step>
Sub2 first, Sub1 third
</Step>
</Step>
</Header1>
</Section1>
<Section2 Number="Section2" Name="concat('NameOfDocument','2')" Title="Title2">
<Step>
Sub1 first
</Step>
<Step>
Sub1 second
<Step>
Sub2 first, Sub1 second
</Step>
</Step>
<Step>
Sub1 third
<Step>
Sub2 first, Sub1 third
</Step>
</Step>
</Section2>
</Volume1>
感谢 Dimitrie Novatchev,我现在有了一些可以处理部分元素内的平坦部分的代码。我有一个与“Section”元素匹配的模板,然后声明一个元素并从“SectionName”、“标题”(有时还包括“标头”)中获取信息,以填写该元素的名称及其属性。我想跳过部分名称、标题,有时还跳过标题,但我不知道如何修改 Dimitrie 的代码来做到这一点。任何建议将不胜感激!谢谢你!
Dimitrie的分组代码:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<Root>
<xsl:apply-templates select="*[1]">
<xsl:with-param name="pScope" select="*"/>
<xsl:with-param name="pElemName" select="name(*[1])"/>
</xsl:apply-templates>
</Root>
</xsl:template>
<xsl:template match="*">
<xsl:param name="pScope"/>
<xsl:param name="pElemName" select="'Step'"/>
<xsl:for-each-group select="$pScope"
group-starting-with="*[name()= name($pScope[1])]">
<xsl:element name="{$pElemName}">
<xsl:value-of select="."/>
<xsl:apply-templates select="current-group()[2]">
<xsl:with-param name="pScope"
select="current-group()[position() > 1]"/>
</xsl:apply-templates>
</xsl:element>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
I'm working on a stylesheet that outputs in a hierarchical format from an input file with almost none. Each section has an extremely flat hierarchy, so I've been using a grouping method that was suggested to me - it groups each set by the first node name, and thus makes a nice heirarchy out of flat sections. This method works great - I just need to modify it to account for elements I want to skip over.
Sample input file (note: there are multiple Header elements per Section):
<Root>
<VolumeName>Volume 1 </VolumeName>
<Section>
<SectionName> Section1 </SectionName>
<Title> Title1 </Title>
<Header> NameOfDocument1 </Header>
<Header> Header1 </Header>
<Sub1> Sub1 first </Sub1>
<Sub1> Sub1 second </Sub1>
<Sub2> Sub2 first, Sub1 second </Sub2>
<Sub1> Sub1 third </Sub1>
<Sub2> Sub2 first, Sub1 third </Sub2>
</Section>
<Section>
<SectionName> Section2 </SectionName>
<Title> Title2 </Title>
<Header> Header2 </Header>
<Sub1> Sub1 first </Sub1>
<Sub1> Sub1 second </Sub1>
<Sub2> Sub2 first, Sub1 second </Sub2>
<Sub1> Sub1 third </Sub1>
<Sub2> Sub2 first, Sub1 third </Sub2>
</Section>
</Root>
The output of the sample input code should look like:
<Volume1>
<Section1 Number="Section1" Name="NameOfDocument1" Title="Title1">
<Header1>
<Step>
Sub1 first
</Step>
<Step>
Sub1 second
<Step>
Sub2 first, Sub1 second
</Step>
</Step>
<Step>
Sub1 third
<Step>
Sub2 first, Sub1 third
</Step>
</Step>
</Header1>
</Section1>
<Section2 Number="Section2" Name="concat('NameOfDocument','2')" Title="Title2">
<Step>
Sub1 first
</Step>
<Step>
Sub1 second
<Step>
Sub2 first, Sub1 second
</Step>
</Step>
<Step>
Sub1 third
<Step>
Sub2 first, Sub1 third
</Step>
</Step>
</Section2>
</Volume1>
Thanks to Dimitrie Novatchev, I now have some code that will handle the flat parts inside the Section elements. I have a template match for the Section element, then I declare an element and grab information from SectionName, Title, and sometimes Header to fill in what the element will be called and its attributes. I want to skip SectionName, Title, and sometimes Header and I'm not sure how to modify Dimitrie's code to do so. Any suggestions would be greatly appreciated! Thank you!
Dimitrie's grouping code:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<Root>
<xsl:apply-templates select="*[1]">
<xsl:with-param name="pScope" select="*"/>
<xsl:with-param name="pElemName" select="name(*[1])"/>
</xsl:apply-templates>
</Root>
</xsl:template>
<xsl:template match="*">
<xsl:param name="pScope"/>
<xsl:param name="pElemName" select="'Step'"/>
<xsl:for-each-group select="$pScope"
group-starting-with="*[name()= name($pScope[1])]">
<xsl:element name="{$pElemName}">
<xsl:value-of select="."/>
<xsl:apply-templates select="current-group()[2]">
<xsl:with-param name="pScope"
select="current-group()[position() > 1]"/>
</xsl:apply-templates>
</xsl:element>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是我的答案或最初的问题的改编,以产生现在想要的结果:
当此转换应用于提供的 XML 文档时:
想要的结果是制作:
Here is the adaptation of my answer or the initial question to produce the result wanted now:
when this transformation is applied on the provided XML document:
the wanted result is produced:
我将坚持我的细粒度遍历方法。此 XSLT 1.0 样式表:
输出:
注意:因为计算的名称比映射更复杂,所以我使用了模式匹配方法。
编辑:仅删除空白文本节点(感谢@Dimitre的评论),因此现在在撒克逊语中也显示正确的结果。
I'll stick to my fine grained traversal approach. This XSLT 1.0 stylesheet:
Output:
Note: Because calculated names are more complex than mapping I've used a pattern matching approach.
Edit: Stripping whitespace only text nodes (thanks to @Dimitre's comments), so now also shows correct result in Saxon.