Xml XSLT组元素
我有一个如下所示的输入xml文件Xml XSLT组元素,xml,xslt,Xml,Xslt,我有一个如下所示的输入xml文件 <FLEX_ATTRIBUTES> <OBJ_ATTRIBUTE> <ATTRIBUTE_NAME>FMGP_CLAIM_DESC</ATTRIBUTE_NAME> <ATTRIBUTE_VALUE>Bull broke leg</ATTRIBUTE_VALUE> </OBJ_ATTRIBUTE> <OBJ_ATTRIBUTE> <ATT
<FLEX_ATTRIBUTES>
<OBJ_ATTRIBUTE>
<ATTRIBUTE_NAME>FMGP_CLAIM_DESC</ATTRIBUTE_NAME>
<ATTRIBUTE_VALUE>Bull broke leg</ATTRIBUTE_VALUE>
</OBJ_ATTRIBUTE>
<OBJ_ATTRIBUTE>
<ATTRIBUTE_NAME>FMGP_CLAIM_TYPE</ATTRIBUTE_NAME>
<ATTRIBUTE_VALUE>Injury</ATTRIBUTE_VALUE>
</OBJ_ATTRIBUTE>
<OBJ_ATTRIBUTE>
<ATTRIBUTE_NAME>FMGP_CLAIM_STATUS</ATTRIBUTE_NAME>
<ATTRIBUTE_VALUE>Settled</ATTRIBUTE_VALUE>
</OBJ_ATTRIBUTE>
<OBJ_ATTRIBUTE>
<ATTRIBUTE_NAME>FMGP_YR_OF_CLAIM</ATTRIBUTE_NAME>
<ATTRIBUTE_VALUE>2009</ATTRIBUTE_VALUE>
</OBJ_ATTRIBUTE>
<OBJ_ATTRIBUTE>
<ATTRIBUTE_NAME>FMGP_CLAIM_AMOUNT</ATTRIBUTE_NAME>
<ATTRIBUTE_VALUE>7000</ATTRIBUTE_VALUE>
</OBJ_ATTRIBUTE>
<OBJ_ATTRIBUTE>
<ATTRIBUTE_NAME>FMGP_CLAIM_DESC</ATTRIBUTE_NAME>
<ATTRIBUTE_VALUE>Stolen tractor</ATTRIBUTE_VALUE>
</OBJ_ATTRIBUTE>
<OBJ_ATTRIBUTE>
<ATTRIBUTE_NAME>FMGP_CLAIM_TYPE</ATTRIBUTE_NAME>
<ATTRIBUTE_VALUE>theft</ATTRIBUTE_VALUE>
</OBJ_ATTRIBUTE>
<OBJ_ATTRIBUTE>
<ATTRIBUTE_NAME>FMGP_CLAIM_STATUS</ATTRIBUTE_NAME>
<ATTRIBUTE_VALUE>Settled</ATTRIBUTE_VALUE>
</OBJ_ATTRIBUTE>
<OBJ_ATTRIBUTE>
<ATTRIBUTE_NAME>FMGP_YR_OF_CLAIM</ATTRIBUTE_NAME>
<ATTRIBUTE_VALUE>2012/ATTRIBUTE_VALUE>
</OBJ_ATTRIBUTE>
<OBJ_ATTRIBUTE>
<ATTRIBUTE_NAME>FMGP_CLAIM_AMOUNT</ATTRIBUTE_NAME>
<ATTRIBUTE_VALUE>16000</ATTRIBUTE_VALUE>
</OBJ_ATTRIBUTE>
FMGP_索赔描述
公牛摔断了腿
FMGP_索赔_类型
损伤
FMGP_索赔_状态
稳定的
FMGP年索赔额
2009
FMGP_索赔金额
7000
FMGP_索赔描述
偷来的拖拉机
FMGP_索赔_类型
盗窃
FMGP_索赔_状态
稳定的
FMGP年索赔额
2012/属性值>
FMGP_索赔金额
16000
我希望得到以下格式的输出xml,其中每个声明都放在PreviousClaim元素中
<PreviousClaims>
<PreviousClaim>
<YrOfClaim>2009</YrOfClaim>
<ClaimType>Injury</ClaimType>
<ClaimDesc>Bull broke leg</ClaimDesc>
<ClaimStatus>Settled</ClaimStatus>
<ClaimAmount>7000</ClaimAmount>
</PreviousClaim>
<PreviousClaim>
<YrOfClaim>2012</YrOfClaim>
<ClaimType>Theft</ClaimType>
<ClaimDesc>Stolen tractor</ClaimDesc>
<ClaimStatus>Settled</ClaimStatus>
<ClaimAmount>17000</ClaimAmount>
</PreviousClaim>
2009
损伤
公牛摔断了腿
稳定的
7000
2012
盗窃
偷来的拖拉机
稳定的
17000
在我的xsl中,我尝试使用如下所示的for each group函数,它将为找到的每个FMGP_CLAIM_DESC创建一个新的PreviousClaim元素,但是我在尝试获取其他元素时遇到困难
<PreviousClaims>
<xsl:for-each-group select="../OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_CLAIM_DESC']" group-by="ATTRIBUTE_VALUE">
<PreviousClaim>
<ClaimDesc><xsl:value-of select="ATTRIBUTE_VALUE"/></ClaimDesc>
</PreviousClaim>
</xsl:for-each-group>
</PreviousClaims>
我已经使用一些定制的逻辑使它工作了,但这不是一个非常优雅的解决方案,我希望利用XSLT2.0中的一些新特性使它更易于阅读和维护
<PreviousClaims>
<xsl:for-each select="../OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_YR_OF_CLAIM']">
<PreviousClaim>
<YrOfClaim><xsl:value-of select="ATTRIBUTE_VALUE"/></YrOfClaim>
<!-- <position><xsl:value-of select="position()"/></position>-->
<xsl:variable name="pos" select="position()"></xsl:variable>
<xsl:for-each select="../OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_CLAIM_TYPE']">
<xsl:if test="position() = $pos">
<ClaimType><xsl:value-of select="ATTRIBUTE_VALUE"/></ClaimType>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="../OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_CLAIM_DESC']">
<xsl:if test="position() = $pos">
<ClaimDesc><xsl:value-of select="ATTRIBUTE_VALUE"/></ClaimDesc>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="../OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_CLAIM_STATUS']">
<xsl:if test="position() = $pos">
<ClaimStatus><xsl:value-of select="ATTRIBUTE_VALUE"/></ClaimStatus>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="../OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_CLAIM_AMOUNT']">
<xsl:if test="position() = $pos">
<ClaimAmount><xsl:value-of select="ATTRIBUTE_VALUE"/></ClaimAmount>
</xsl:if>
</xsl:for-each>
</PreviousClaim>
</xsl:for-each>
</PreviousClaims>
使用以开头的
组:
<xsl:template match="FLEX_ATTRIBUTES">
<Claims>
<xsl:for-each-group select="OBJ_ATTRIBUTE" group-starting-with="OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_CLAIM_DESC']">
<PreviousClaim>
<xsl:apply-templates select="current-group()"/>
</PreviousClaim>
</xsl:for-each-group>
</Claims>
</xsl:template>
<xsl:template match="OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_CLAIM_DESC']">
<ClaimDesc>
<xsl:value-of select="ATTRIBUTE_VALUE"/>
</ClaimDesc>
</xsl:template>
<xsl:template match="OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_CLAIM_TYPE']">
<ClaimType>
<xsl:value-of select="ATTRIBUTE_VALUE"/>
</ClaimType>
</xsl:template>
<!-- add similar templates here for the other attribute types -->
如果您需要更改顺序,那么我仍然会使用分组和模板,但是您需要通过以下操作列出您想要的顺序:
<xsl:template match="FLEX_ATTRIBUTES">
<Claims>
<xsl:for-each-group select="OBJ_ATTRIBUTE" group-starting-with="OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_CLAIM_DESC']">
<PreviousClaim>
<xsl:apply-templates select="current-group()[self::OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_YR_OF_CLAIM']], current-group()[self::OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_CLAIM_TYPE']], ., current-group()[self::OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_CLAIM_STATUS']], current-group()[self::OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_CLAIM_AMOUNT']]"/>
</PreviousClaim>
</xsl:for-each-group>
</Claims>
</xsl:template>
下面是一个完整的XSLT样式表,基于@MartinHonnen给出的答案
样式表
样式表只有一个用于OBJ_属性
元素的通用模板。原则上,它也可以处理其他类型的属性,因为它们的结构是相同的
元素名称不应再包含。
,并且是CAMELCASE,这一事实使问题稍微复杂化
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="FLEX_ATTRIBUTES">
<PreviousClaims>
<xsl:for-each-group select="OBJ_ATTRIBUTE" group-starting-with="OBJ_ATTRIBUTE[ATTRIBUTE_NAME='FMGP_CLAIM_DESC']">
<PreviousClaim>
<xsl:apply-templates select="current-group()"/>
</PreviousClaim>
</xsl:for-each-group>
</PreviousClaims>
</xsl:template>
<xsl:template match="OBJ_ATTRIBUTE">
<xsl:variable name="step-1" select="tokenize(lower-case(substring-after(ATTRIBUTE_NAME,'FMGP')),'_')"/>
<xsl:variable name="step-2">
<xsl:for-each select="$step-1">
<xsl:value-of select="concat(upper-case(substring(.,1,1)),substring(., 2),' '[not(last())])"/>
</xsl:for-each>
</xsl:variable>
<xsl:element name="{$step-2}">
<xsl:value-of select="ATTRIBUTE_VALUE"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
输出
请注意,元素的顺序与预期输出中的顺序不同。如果订购对你来说很重要,那么我和Martin Honnen的答案都行不通
<?xml version="1.0" encoding="UTF-8"?>
<PreviousClaims>
<PreviousClaim>
<ClaimDesc>Bull broke leg</ClaimDesc>
<ClaimType>Injury</ClaimType>
<ClaimStatus>Settled</ClaimStatus>
<YrOfClaim>2009</YrOfClaim>
<ClaimAmount>7000</ClaimAmount>
</PreviousClaim>
<PreviousClaim>
<ClaimDesc>Stolen tractor</ClaimDesc>
<ClaimType>theft</ClaimType>
<ClaimStatus>Settled</ClaimStatus>
<YrOfClaim>2012</YrOfClaim>
<ClaimAmount>16000</ClaimAmount>
</PreviousClaim>
</PreviousClaims>
公牛摔断了腿
损伤
稳定的
2009
7000
偷来的拖拉机
盗窃
稳定的
2012
16000
谢谢你的回答,真的很有帮助!订单不重要,因此这将非常有效。再次感谢!谢谢Mathias现在应该可以很好地利用它了。