Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml XSLT组元素_Xml_Xslt - Fatal编程技术网

Xml XSLT组元素

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

我有一个如下所示的输入xml文件

<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现在应该可以很好地利用它了。