继续提出有关"How to create subsets of a single set of elements with XSLT?"
的问题我希望我的问题更进一步: 我最初将以下XML作为原始XML:
<Set>
<Element name="Superset1_Set1_Element1"/>
<Element name="Superset1_Set1_Element2"/>
<Element name="Superset1_Set2_Element1"/>
<Element name="Superset2_Set1_Element1"/>
<Element name="Superset2_Set2_Element1"/>
</Set>
并要求XSL Transformation产生以下输出:
<Superset name="Superset1">
<Set name="Set1">
<Element name="Element1"/>
<Element name="Element2"/>
</Set>
<Set name="Set2">
<Element name="Element1"/>
</Set>
</Superset>
<Superset name="Superset2">
<Set name="Set1">
<Element name="Element1"/>
</Set>
<Set name="Set2">
<Element name="Element1"/>
</Set>
</Superset>
Tomalak和annakata都给了我一个有效的解决方案。我选择了Tomalak,因为它使用的模板在我看来更具人性化。
问题是我的XML实际上是以下形式:
<Set>
<Element name="Classic_Authors_Dante_Alighieri_The_Divine_Comedy"/>
<Element name="Classic_Authors_Dante_Alighieri_Convivio"/>
<Element name="Classic_Authors_Miguel_de_Cervantes_Saavedra_Don_Quixote"/>
<Element name="Contemporary_Authors_Stephen_King_Just_After_Sunset"/>
<Element name="Contemporary_Authors_Stephen_King_Desperation"/>
</Set>
Supersets,sets和elements在其中包含不同数量的下划线。 在上面的例子中有两个超集:'Classic_Authors'和'Contemporary_Authors'。这三组是'Dante_Alighieri','Miguel_de_Cervantes_Saavedra'和'Stephen_King'。
输出XML应为:
<Superset name="Classic_Authors">
<Set name="Dante_Alighieri">
<Element name="The_Divine_Comedy"/>
<Element name="Convivio"/>
</Set>
<Set name="Miguel_de_Cervantes_Saavedra">
<Element name="Don_Quixote"/>
</Set>
</Superset>
<Superset name="Contemporary_Authors">
<Set name="Stephen_King">
<Element name="Just_After_Sunset"/>
<Element name="Desperation"/>
</Set>
</Superset>
那怎么样,我可以使用Tomalak的解决方案吗?也就是说,我应该如何准备我的xml来使用他的算法呢?可以在单个XSLT中完成吗?可能有另一种解决方案吗?
非常感谢!
答案 0 :(得分:1)
正如我在上一个问题中对我的回答的评论中所说,在开始解决此问题之前,您需要一个包含固定和已知集合名称的文件。理想情况下,它的结构如下:
<!-- SetNames.xml --->
<names>
<Superset name="Classic_Authors">
<Set name="Dante_Alighieri" />
<Set name="Miguel_de_Cervantes_Saavedra" />
</Superset>
<Superset name="Contemporary_Authors">
<Set name="Stephen_King" />
</Superset>
</names>
如果没有这样的文件,问题将无法解决。现在你有了很好的结构化名称,你可以根据它进行分组(实质上,它已经是输出格式,你需要做的只是匹配你的数据):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:param name="pSetFile" select="'SetNames.xml'" />
<xsl:variable name="root" select="/" />
<xsl:template match="/Set">
<xsl:copy>
<xsl:variable name="vSetDoc" select="document($pSetFile)" />
<xsl:apply-templates select="$vSetDoc/names/Superset">
<xsl:sort select="@name" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="Superset">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates select="Set">
<xsl:sort select="@name" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="Set">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:variable name="vPrefix" select="
concat(../@name, '_', @name, '_')
" />
<xsl:apply-templates select="
$root/Set/Element[starts-with(@name, $vPrefix)]
">
<xsl:sort select="@name" />
<xsl:with-param name="pPrefix" select="$vPrefix" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="Element">
<xsl:param name="pPrefix" select="''" />
<xsl:copy>
<xsl:attribute name="name">
<xsl:value-of select="substring-after(@name, $pPrefix)" />
</xsl:attribute>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当应用于您的输入时,会产生:
<Set>
<Superset name="Classic_Authors">
<Set name="Dante_Alighieri">
<Element name="Convivio" />
<Element name="The_Divine_Comedy" />
</Set>
<Set name="Miguel_de_Cervantes_Saavedra">
<Element name="Don_Quixote" />
</Set>
</Superset>
<Superset name="Contemporary_Authors">
<Set name="Stephen_King">
<Element name="Desperation" />
<Element name="Just_After_Sunset" />
</Set>
</Superset>
</Set>
由于SetNames.xml
基本上已经分组,因此不需要进一步(Muenchian)分组。上面最慢的表达方式是:
$root/Set/Element[starts-with(@name, $vPrefix)]
这种“表扫描”类型的表达式正是<xsl:key>
有用的地方,但由于问题的性质,它不能在这里使用。
答案 1 :(得分:0)
问题是关于元素的所有信息都塞满了一个属性。您应该将数据的语义不同部分分成单独的元素或单独的属性,即:
<Set>
<Element title="The Divine Comedy" author="Dante Alighieri" category="Classic Authors"/>
...
如果您对现有元素感到困惑,恐怕我没有一个好的解决方案。作为一个人,我甚至很难确定“名称”的哪些部分是标题,作者或类别。我想不出解析数据的简单方法。
答案 2 :(得分:0)
没有确定性的方法将书名与作者姓名分开。每个下划线的数量各不相同。
唯一的解决方案是让发件人的作者以某种方式更改格式,从而为您的输入添加更多信息。 (也许书和作者之间有两个下划线?)