我有一个xml:
<FlightDetails1>
<CouponNumber1>1</CouponNumber1>
<ServiceClass1>Y</ServiceClass1>
</FlightDetails1>
<FlightDetails2>
<CouponNumber2>2</CouponNumber2>
<ServiceClass2>Y</ServiceClass2>
</FlightDetails2>
<FlightDetails3>
<CouponNumber3></CouponNumber3>
<ServiceClass3>N</ServiceClass3>
</FlightDetails3>
需要将此xml转换为以下格式:
<FlightDetails>
<CouponNumber>1</CouponNumber>
<ServiceClass>Y</ServiceClass>
</FlightDetails>
<FlightDetails>
<CouponNumber>2</CouponNumber>
<ServiceClass>Y</ServiceClass>
</FlightDetails>
<FlightDetails>
<CouponNumber></CouponNumber>
<ServiceClass>N</ServiceClass>
</FlightDetails>
以前,当标签类似于<FlightDetails> and <CouponNumber>
时,我在XSLT中使用了'copy-of'功能。在重命名标签的情况下,使用xslt实现这一目标的最简单方法是什么?
XSLT:
<xsl:output indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select="//FlightDetails1"/>
</xsl:template>
答案 0 :(得分:1)
这是一个通用版本
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- the identity template -->
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<!-- elements whose names end with digits -->
<xsl:template match="*[
starts-with(name(), translate(name(), '01234567890', ''))
and substring-after(name(), translate(name(), '01234567890', ''))
]">
<xsl:element name="{translate(name(), '01234567890', '')}">
<xsl:apply-templates select="node() | @*" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
第二个模板匹配所有以数字结尾的元素......
删除名称中的所有数字
translate(name(), '01234567890', '') := 'FlightDetails1' -> 'FlightDetails'
确保它与中间数字的元素不匹配
starts-with('FlightDetails1', 'FlightDetails') := true
starts-with('Flight1Details', 'FlightDetails') := false
检查字符串开头后有什么东西(按照定义,这只能是一个或多个数字,所有其他元素都已经失败了以前的测试)
substring-after('FlightDetails1', 'FlightDetails') := '1' (evaluates to true)
这样,模板会匹配letters123
形式的任何名称元素。
<xsl:element name="{translate(name(), '01234567890', '')}">
然后重新创建没有尾随数字的元素。
答案 1 :(得分:0)
如果您不希望元素名称持久存在,则不能再使用copy
(或者使用它的方式复制)。
相反,请在单独的模板中匹配这些元素,例如:
<xsl:template match="*[starts-with(name(),'FlightDetails')]">
<xsl:element name="FlightDetails">
<!--Further processing-->
</xsl:element>
</xsl:template>
此模板匹配所有形式的FlightDetails
元素,也就是说,无论元素名称末尾的数字如何。然后,使用xsl:element
指令创建一个名为“FlightDetails”的新元素。
然后,继续为您希望规范化的其他元素编写类似的模板。请注意,现在apply-templates/
已经发挥作用,将其留给处理器决定接下来应用哪个模板。
总结所有这些的样式表(我在输入XMl中添加了root
元素以使其格式正确):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/root">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*[starts-with(name(),'FlightDetails')]">
<xsl:element name="FlightDetails">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*[starts-with(name(),'CouponNumber')]">
<xsl:element name="CouponNumber">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*[starts-with(name(),'ServiceClass')]">
<xsl:element name="ServiceClass">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="text()">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
提供以下输出:
<?xml version="1.0" encoding="UTF-8"?>
<FlightDetails>
<CouponNumber>1</CouponNumber>
<ServiceClass>Y</ServiceClass>
</FlightDetails>
<FlightDetails>
<CouponNumber>2</CouponNumber>
<ServiceClass>Y</ServiceClass>
</FlightDetails>
<FlightDetails>
<CouponNumber/>
<ServiceClass>N</ServiceClass>
</FlightDetails>