使用XSL进行XML到XML转换

时间:2012-01-03 02:06:42

标签: xml xslt

我需要将xml数据转换为不同的格式。我做了很少的XSL东西,我的网络搜索并没有给我所需的结果。我有这个示例xml:

 <MailStatusReport>
        <Output>
            <ColMetaData ColCount="5">
                <ColList>
                    <Col  Name="parcelid" Pos="1"/>
                    <Col  Name="currentlocationid" Pos="2"/>
                    <Col  Name="deliverystatus" Pos="4"/>
                    <Col  Name="requestedlocationid" Pos="3"/>
                    <Col  Name="requestor" Pos="5"/>
                </ColList>
            </ColMetaData>
            <RowList>
                <Row>
                    <ColList>
                        <Col Pos="2">Delaware</Col>
                        <Col Pos="1">001</Col>
                        <Col Pos="3">NewYork</Col>
                        <Col Pos="4">InRoute</Col>
                        <Col Pos="5">John</Col>

                    </ColList>
                </Row>
                <Row>
                    <ColList>
                        <Col Pos="1">002</Col>
                        <Col Pos="2">Sanjose</Col>
                        <Col Pos="3">Michigan</Col>
                        <Col Pos="4">Delivered</Col>
                        <Col Pos="5">Rob</Col>
                    </ColList>
                </Row>
            </RowList>
        </Output>
</MailStatusReport>

期望的输出:

   <MailStatusReport>
        <Row parcelid="001" currentlocationid="Delaware" requestedlocationid="NewYork" deliverystatus="InRoute" requestor="John"/>
        <Row parcelid="002" currentlocationid="Sanjose" requestedlocationid="Michigan" deliverystatus="Delivered" requestor="Rob"/>
  </MailStatusReport> 

很少有事情需要注意:

  1. 输入xml中ColMetaData / ColList / Col的Name属性最终作为输出xml的每个Row元素的属性名称。
  2. 输入xml中RowList / Row / ColList / Col的值最终作为属性的输出xml中的属性值,该属性具有与ColMetaData / ColList / Col部分中相同的Pos。
  3. ColMetaData的ColCount属性值得信赖,如果需要可以用作计数器。
  4. 我能想到的伪代码是:

     For each CurrentRow in the RowList
       Begin Building OutputRow
        For each Col in ColMetaData/ColList
          attrName = ColMetaData/ColList/Col/Name
          attrPos = ColMetaData/ColList/Col/Pos
          attrVal = CurrentRow/ColList/Col[@Pos=$attrPos]
          Add $attrName=$attrVal to the outputRow
    

    我很感激能得到的任何帮助! 谢谢 SRINIVAS

1 个答案:

答案 0 :(得分:3)

此转化

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

 <xsl:key name="kColNameByPos" match="Col/@Name"
  use="../@Pos"/>

 <xsl:template match="/*">
  <MailStatusReport>
   <xsl:apply-templates/>
  </MailStatusReport>
 </xsl:template>

 <xsl:template match="Row">
  <Row>
    <xsl:apply-templates select="*/*">
      <xsl:sort select="@Pos" data-type="number"/>
    </xsl:apply-templates>
  </Row>
 </xsl:template>

 <xsl:template match="Row/ColList/Col">
  <xsl:attribute name="{key('kColNameByPos', @Pos)}">
   <xsl:value-of select="."/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<MailStatusReport>
    <Output>
        <ColMetaData ColCount="5">
            <ColList>
                <Col  Name="parcelid" Pos="1"/>
                <Col  Name="currentlocationid" Pos="2"/>
                <Col  Name="deliverystatus" Pos="4"/>
                <Col  Name="requestedlocationid" Pos="3"/>
                <Col  Name="requestor" Pos="5"/>
            </ColList>
        </ColMetaData>
        <RowList>
            <Row>
                <ColList>
                    <Col Pos="2">Delaware</Col>
                    <Col Pos="1">001</Col>
                    <Col Pos="3">NewYork</Col>
                    <Col Pos="4">InRoute</Col>
                    <Col Pos="5">John</Col>
                </ColList>
            </Row>
            <Row>
                <ColList>
                    <Col Pos="1">002</Col>
                    <Col Pos="2">Sanjose</Col>
                    <Col Pos="3">Michigan</Col>
                    <Col Pos="4">Delivered</Col>
                    <Col Pos="5">Rob</Col>
                </ColList>
            </Row>
        </RowList>
    </Output>
</MailStatusReport>

生成想要的正确结果

<MailStatusReport>
   <Row parcelid="001"
        currentlocationid="Delaware"
        requestedlocationid="NewYork"
        deliverystatus="InRoute"
        requestor="John"/>
   <Row parcelid="002"
        currentlocationid="Sanjose"
        requestedlocationid="Michigan"
        deliverystatus="Delivered"
        requestor="Rob"/>
</MailStatusReport>

<强>解释

  1. 使用 <xsl:sort> 排序属性生成的结果。

  2. 使用 <xsl:key> key() 函数定义列名和列位置之间的映射 - 以便更方便地计算正在生成的属性的名称。

  3. 使用 AVT (属性值模板)从计算值生成属性名称。