将xml转换为层次结构 - 需要轻推

时间:2014-07-15 11:07:56

标签: xml xslt-1.0 hierarchy

我已经在这个主板上研究了各种解决方案,但我担心我仍然有点卡住 - 我是否需要使用密钥进行Muenchian分组,或者在项目类型W之前使用兄弟帮助。

简而言之,有多个faRecord节点 - 每个记录中的第一个项目元素表示它是什么类型的记录 - 这里是C,W,但也有其他类型。

我到目前为止的XSL会将这些记录转换为类别和工作代码,但我很难知道如何将工作代码嵌入到类别中。序列可以是C W W W C W C C W W W等。这些值都不是唯一的。 (嵌套在工作代码中的项目等等 - 但这是第一步。每个类别将包含0个或更多工作代码。每个工作代码可能包含0个或更多项目。)

这是XML

<?xml version="1.0" encoding="UTF-8"?>
<EstimateDisplayRequest>
   <facXML>      
      <faRecord>
         <recordCode>33</recordCode>
         <item>
            <itemMapCode>1</itemMapCode>
            <itemValue>C</itemValue>
         </item>
         <item>
            <itemMapCode>80</itemMapCode>
            <itemValue>0</itemValue>
         </item>
         <item>
            <itemMapCode>81</itemMapCode>
            <itemValue>INTERNAL CREATIVE</itemValue>
         </item>
         <item>
            <itemMapCode>82</itemMapCode>
            <itemValue>TOTAL INTERNAL CREAT</itemValue>
         </item>             
      </faRecord>
      <faRecord>
         <recordCode>33</recordCode>
         <item>
            <itemMapCode>1</itemMapCode>
            <itemValue>W</itemValue>
         </item>
         <item>
            <itemMapCode>41</itemMapCode>
            <itemValue>0</itemValue>
         </item>
         <item>
            <itemMapCode>42</itemMapCode>
            <itemValue>TI</itemValue>
         </item>
         <item>
            <itemMapCode>43</itemMapCode>
            <itemValue>Time Work Code</itemValue>
         </item>
      </faRecord>
      <faRecord>
         <recordCode>33</recordCode>
         <item>
            <itemMapCode>1</itemMapCode>
            <itemValue>W</itemValue>
         </item>
         <item>
            <itemMapCode>41</itemMapCode>
            <itemValue>0</itemValue>
         </item>
         <item>
            <itemMapCode>42</itemMapCode>
            <itemValue>TI</itemValue>
         </item>
         <item>
            <itemMapCode>43</itemMapCode>
            <itemValue>Time Work Code</itemValue>
         </item>
      </faRecord>
      <faRecord>
         <recordCode>33</recordCode>
         <item>
            <itemMapCode>1</itemMapCode>
            <itemValue>C</itemValue>
         </item>
         <item>
            <itemMapCode>80</itemMapCode>
            <itemValue>1</itemValue>
         </item>
         <item>
            <itemMapCode>81</itemMapCode>
            <itemValue>EXTERNAL CREATIVE</itemValue>
         </item>
         <item>
            <itemMapCode>82</itemMapCode>
            <itemValue>TOTAL EXTERNAL CREAT</itemValue>
         </item>             
      </faRecord>
      <faRecord>
         <recordCode>33</recordCode>
         <item>
            <itemMapCode>1</itemMapCode>
            <itemValue>W</itemValue>
         </item>
         <item>
            <itemMapCode>41</itemMapCode>
            <itemValue>0</itemValue>
         </item>
         <item>
            <itemMapCode>42</itemMapCode>
            <itemValue>TI2</itemValue>
         </item>
         <item>
            <itemMapCode>43</itemMapCode>
            <itemValue>Time Work Code</itemValue>
         </item>
      </faRecord>
   </facXML>
</EstimateDisplayRequest>

这是我到目前为止的XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="EstimateDisplayRequest">
        <MCSResponse>
            <EstimateDisplayResponse>
                <xsl:apply-templates select="*" mode="EstimateDisplayResponse" />
            </EstimateDisplayResponse>
        </MCSResponse>
    </xsl:template>

    <xsl:template match="faRecord[item/itemMapCode='1' and item/itemValue='C']" mode="EstimateDisplayResponse">
            <EstimateDisplayResponseDetailCategory>
                    <xsl:attribute name="id"><xsl:number/></xsl:attribute>
                    <xsl:apply-templates select="child::*[not(self::recordCode)]" />
            </EstimateDisplayResponseDetailCategory>
    </xsl:template>

    <xsl:template match="faRecord[item/itemMapCode='1' and item/itemValue='W']" mode="EstimateDisplayResponse">
            <EstimateDisplayResponseDetailWorkcode>
                    <xsl:attribute name="id"><xsl:number/></xsl:attribute>
                    <xsl:apply-templates select="child::*[not(self::recordCode)]" />
            </EstimateDisplayResponseDetailWorkcode>
    </xsl:template>


    <xsl:template match="item[itemMapCode='1']" />     

    <xsl:template match="item[itemMapCode='80']" >
        <CategoryCode>
            <xsl:value-of select="./itemValue" />
        </CategoryCode>
    </xsl:template>
    <xsl:template match="item[itemMapCode='81']" >
        <CategoryName>
            <xsl:value-of select="./itemValue" />
        </CategoryName>
    </xsl:template>
    <xsl:template match="item[itemMapCode='82']" >
        <CategoryTotalName>
            <xsl:value-of select="./itemValue" />
        </CategoryTotalName>
    </xsl:template>    

    <xsl:template match="item[itemMapCode='41']" >
        <WorkCodeCategory>
            <xsl:value-of select="./itemValue" />
        </WorkCodeCategory>
    </xsl:template>
    <xsl:template match="item[itemMapCode='42']" >
        <WorkCode>
            <xsl:value-of select="./itemValue" />
        </WorkCode>
    </xsl:template>
    <xsl:template match="item[itemMapCode='43']" >
        <WorkCodeName>
            <xsl:value-of select="./itemValue" />
        </WorkCodeName>
    </xsl:template>    
</xsl:stylesheet>

TIA!

[抱歉,我也应该列出输出 - 类别列表。我尝试使用for-each用于跟随兄弟姐妹的类别,但是当我走下节点时,我最终得到所有剩余的工作代码元素 - 这是我猜的:(]

<mcsresponse>
    <estimatedisplayresponse>
        <estimatedisplayresponsedetailcategory id="1">
            <categorycode>0</categorycode>
            <categoryname>INTERNAL CREATIVE</categoryname>
            <categorytotalname>TOTAL INTERNAL CREAT</categorytotalname>                
            <estimatedisplayresponsedetailworkcode id="2">
                <workcodecategory>0</workcodecategory>
                <workcode>TI</workcode>
                <workcodename>Time Work Code</workcodename>                    
            </estimatedisplayresponsedetailworkcode>
            <estimatedisplayresponsedetailworkcode id="3">
                <workcodecategory>0</workcodecategory>
                <workcode>TI</workcode>
                <workcodename>Time Work Code</workcodename>                    
            </estimatedisplayresponsedetailworkcode>
        </estimatedisplayresponsedetailcategory>
        <estimatedisplayresponsedetailcategory id="4">
            <categorycode>0</categorycode>
            <categoryname>INTERNAL CREATIVE</categoryname>
            <categorytotalname>TOTAL INTERNAL CREAT</categorytotalname>               
            <else>YNNYN</else>
            <estimatedisplayresponsedetailworkcode id="5">
                <workcodecategory>0</workcodecategory>
                <workcode>TI</workcode>
                <workcodename>Time Work Code</workcodename>                    
            </estimatedisplayresponsedetailworkcode>
        </estimatedisplayresponsedetailcategory>
    </estimatedisplayresponse>
</mcsresponse>

1 个答案:

答案 0 :(得分:1)

此XSLT 1.0转换:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" />
  <xsl:strip-space elements="*" />

  <xsl:key name="kWork" match="faRecord[item[itemMapCode = 1]/itemValue = 'W']" use="
    generate-id(preceding-sibling::faRecord[item[itemMapCode = 1]/itemValue = 'C'][1])
  " />

  <xsl:template match="EstimateDisplayRequest">
    <MCSResponse>
      <EstimateDisplayResponse>
        <xsl:apply-templates select="*/faRecord[item[itemMapCode = 1]/itemValue = 'C']" />
      </EstimateDisplayResponse>
    </MCSResponse>
  </xsl:template>

  <xsl:template match="faRecord[item[itemMapCode = 1]/itemValue = 'C']">
    <EstimateDisplayResponseDetailCategory>
      <xsl:attribute name="id"><xsl:number/></xsl:attribute>
      <xsl:apply-templates select="item" />
      <xsl:apply-templates select="key('kWork', generate-id())" />
    </EstimateDisplayResponseDetailCategory>
  </xsl:template>

  <xsl:template match="faRecord[item[itemMapCode = 1]/itemValue = 'W']">
    <EstimateDisplayResponseDetailWorkcode>
      <xsl:attribute name="id"><xsl:number/></xsl:attribute>
      <xsl:apply-templates select="item" />
    </EstimateDisplayResponseDetailWorkcode>
  </xsl:template>

  <!-- this catches <recordCode> and unknown elements -->
  <xsl:template match="faRecord/*" />

  <xsl:template match="faRecord/item">
    <xsl:variable name="elemName">
      <xsl:choose>
        <xsl:when test="itemMapCode = 41">WorkCodeCategory</xsl:when>
        <xsl:when test="itemMapCode = 42">WorkCode</xsl:when>
        <xsl:when test="itemMapCode = 43">WorkCodeName</xsl:when>
        <xsl:when test="itemMapCode = 80">CategoryCode</xsl:when>
        <xsl:when test="itemMapCode = 81">CategoryName</xsl:when>
        <xsl:when test="itemMapCode = 82">CategoryTotalName</xsl:when>
      </xsl:choose>
    </xsl:variable>

    <xsl:if test="$elemName != ''">
      <xsl:element name="{$elemName}">
        <xsl:value-of select="./itemValue" />
      </xsl:element>
    </xsl:if>
    <xsl:if test="$elemName = '' and itemMapCode != 1">
      <xsl:message>Warning: no mapping for itemMapCode '<xsl:value-of select="itemMapCode" />'</xsl:message>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

给了我

<MCSResponse>
   <EstimateDisplayResponse>
      <EstimateDisplayResponseDetailCategory id="1">
         <CategoryCode>0</CategoryCode>
         <CategoryName>INTERNAL CREATIVE</CategoryName>
         <CategoryTotalName>TOTAL INTERNAL CREAT</CategoryTotalName>
         <EstimateDisplayResponseDetailWorkcode id="2">
            <WorkCodeCategory>0</WorkCodeCategory>
            <WorkCode>TI</WorkCode>
            <WorkCodeName>Time Work Code</WorkCodeName>
         </EstimateDisplayResponseDetailWorkcode>
         <EstimateDisplayResponseDetailWorkcode id="3">
            <WorkCodeCategory>0</WorkCodeCategory>
            <WorkCode>TI</WorkCode>
            <WorkCodeName>Time Work Code</WorkCodeName>
         </EstimateDisplayResponseDetailWorkcode>
      </EstimateDisplayResponseDetailCategory>
      <EstimateDisplayResponseDetailCategory id="4">
         <CategoryCode>1</CategoryCode>
         <CategoryName>EXTERNAL CREATIVE</CategoryName>
         <CategoryTotalName>TOTAL EXTERNAL CREAT</CategoryTotalName>
         <EstimateDisplayResponseDetailWorkcode id="5">
            <WorkCodeCategory>0</WorkCodeCategory>
            <WorkCode>TI2</WorkCode>
            <WorkCodeName>Time Work Code</WorkCodeName>
         </EstimateDisplayResponseDetailWorkcode>
      </EstimateDisplayResponseDetailCategory>
   </EstimateDisplayResponse>
</MCSResponse>

<xsl:key>为每个类型W记录索引前一个类型C记录的唯一ID。

通过这种方式,可以通过

轻松处理所有类型C记录
<xsl:apply-templates select="*/faRecord[item[itemMapCode = 1]/itemValue = 'C']" />

及其各自的类型W通过

记录
<xsl:apply-templates select="`key('kWork', generate-id()) />