我是XSLT世界的新手。我在这里发现了一些有帮助的线索,但由于我并不真正理解我在做什么,所以我有点卡住了。我试图循环并格式化一些嵌套的XML。
我的XML
<?xml version="1.0" encoding="UTF-8"?>
<exchange>
<vco>
<vco.srs>
<vco_crsc.vco.srs>BUUBMS</vco_crsc.vco.srs>
<vco_prgc.vco.srs>BUBSBAT02</vco_prgc.vco.srs>
<vco_rouc.vco.srs>USMANG</vco_rouc.vco.srs>
<cbo>
<cbo.srs>
<cbo_occl.cbo.srs>AJ</cbo_occl.cbo.srs>
</cbo.srs>
<cbo.srs>
<cbo_occl.cbo.srs>FJ</cbo_occl.cbo.srs>
</cbo.srs>
</cbo>
</vco.srs>
</vco>
</exchange>
通过阅读另一篇类似的帖子,我创建了一个基于模板的代码。模板功能,但理想情况下我希望它的格式不同,因为模板会丢失字段格式。假设我需要另一个模板定义,但正如我所说,不确定我在做什么!
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="/root">
<ImportTask>
<xsl:apply-templates select="CourseDetails"/>-<xsl:apply-templates select="CourseOcc"/>
</ImportTask>
</xsl:template>
<xsl:template match="CourseDetails">
<Courses>
<xsl:for-each select="exchange/vco/vco.srs">
<Course>
<CourseCode><xsl:value-of select="vco_crsc.vco.srs"/></CourseCode>-<Programmecode><xsl:value-of select="vco_prgc.vco.srs"/></Programmecode>-<Routecode><xsl:value-of select="vco_rouc.vco.srs"/></Routecode>
</Course>
</xsl:for-each>
</Courses>
</xsl:template>
<xsl:template match="CourseOcc">
<Occurences>
<xsl:for-each select="exchange/cbo/cbo.srs">
<Occur>
<OccurCode><xsl:value-of select="cbo_occl.cbo.srs"/></OccurCode>
</Occur>
</xsl:for-each>
</Occurences>
</xsl:template>
</xsl:stylesheet>
这是输出:
BUUBMS
BUBSBAT02
USMANG
AJ
FJ
这一切都非常好但不是我想要的。 理想情况下,我希望输出为:
<ImportTask>
<Courses>
<Course>BUUBMS-BUBSBAT02-USMANG-AJ</Course>
<Course>BUUBMS-BUBSBAT02-USMANG-FJ<Course>
</Courses>
</ImportTask>
我猜我需要设置更多的模板代码,但我不确定究竟是什么?
有人能指出我正确的方向还是告诉我是否有更好的方法?
非常感谢
答案 0 :(得分:0)
以下xslt将您的输入传输到所需的输出。在那里,只使用了两个模板,一个用于根元素,一个用于<cbo_occl.cbo.srs>
。后者选择以&#34; vco _&#34;开头的元素的文本节点。在该元素之前,将它们连接起来并最终打印出自己的内容。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="/exchange">
<ImportTask>
<Courses>
<xsl:apply-templates select="//cbo_occl.cbo.srs"/>
</Courses>
</ImportTask>
</xsl:template>
<xsl:template match="cbo_occl.cbo.srs">
<Course>
<!-- select all text-Nodes of vco_* elements -->
<xsl:for-each select="../../../*[matches(name(),'^vco_.*')]/text()">
<xsl:value-of select="concat(.,'-')"/>
</xsl:for-each>
<xsl:value-of select="."/>
</Course>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
您的XSLT中有许多不同的模板匹配
<xsl:template match="/root">
<xsl:template match="CourseDetails">
<xsl:template match="CourseOcc">
但是,当您使用具有匹配项的模板时,这些模板仅在与输入XML文档中的节点匹配时才适用。你不能在这里使用任意名称。因为您的输入XML没有名为root
,CourseDetails
或CourseOcc
的元素,所以这些模板永远不会被调用。
您获得当前输出的原因是由于XSLT的built-in template规则,当您自己的XSLT中没有匹配的模板模板时(这种情况就是这种情况)适用。
我认为您尝试做的事实上是通过“命名”模板实现的,这将允许您使用任意名称。因此,您的XSLT将更加正确地编写:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="/">
<ImportTask>
<xsl:call-template name="CourseDetails"/>
<xsl:text>-</xsl:text>
<xsl:call-template name="CourseOcc"/>
</ImportTask>
</xsl:template>
<xsl:template name="CourseDetails">
<Courses>
<xsl:for-each select="exchange/vco/vco.srs">
<Course>
<CourseCode><xsl:value-of select="vco_crsc.vco.srs"/></CourseCode>
<xsl:text>-</xsl:text>
<Programmecode><xsl:value-of select="vco_prgc.vco.srs"/></Programmecode>
<xsl:text>-</xsl:text>
<Routecode><xsl:value-of select="vco_rouc.vco.srs"/></Routecode>
</Course>
</xsl:for-each>
</Courses>
</xsl:template>
<xsl:template name="CourseOcc">
<Occurences>
<xsl:for-each select="exchange/cbo/cbo.srs">
<Occur>
<OccurCode><xsl:value-of select="cbo_occl.cbo.srs"/></OccurCode>
</Occur>
</xsl:for-each>
</Occurences>
</xsl:template>
</xsl:stylesheet>
注意第一个模板仍然是模板匹配,但是匹配/
而不是/root
,其中/
代表“文档节点”。这是XSLT首先匹配的模板。
话虽如此,您实际上并不需要在此处使用命名模板。您可以通过常规模板匹配实现所需的功能。在这种情况下,这种XSLT可能更可取
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="/exchange">
<ImportTask>
<Courses>
<xsl:apply-templates select="vco/vco.srs"/>
</Courses>
<xsl:if test="cbo/cbo.srs">
<xsl:text>-</xsl:text>
<Occurences>
<xsl:apply-templates select="cbo/cbo.srs"/>
</Occurences>
</xsl:if>
</ImportTask>
</xsl:template>
<xsl:template match="vco.srs">
<Course>
<CourseCode><xsl:value-of select="vco_crsc.vco.srs"/></CourseCode>
<xsl:text>-</xsl:text>
<Programmecode><xsl:value-of select="vco_prgc.vco.srs"/></Programmecode>
<xsl:text>-</xsl:text>
<Routecode><xsl:value-of select="vco_rouc.vco.srs"/></Routecode>
</Course>
</xsl:template>
<xsl:template match="cbo.srs">
<Occur>
<OccurCode><xsl:value-of select="cbo_occl.cbo.srs"/></OccurCode>
</Occur>
</xsl:template>
</xsl:stylesheet>