基于节点的值转换XML(Transforming xml based on node values)

2019-10-28 13:18发布

我的要求是稍微复杂one.I有以下输入XML:

<results>
   <row>
      <CASEID>C1</CASEID>
      <CASEBA>MEDICAID</CASEBA>
      <ISSUEID>I1</ISSUEID>
      <ISSUEBA>MEDICAID</ISSUEBA>
      <OBJECTID>1</OBJECTID>
   </row>
   <row>
      <CASEID>C1</CASEID>
      <CASEBA>MEDICAID</CASEBA>
      <ISSUEID>I2</ISSUEID>
      <ISSUEBA>MEDICAID</ISSUEBA>
      <OBJECTID>2</OBJECTID>
   </row>
   <row>
      <CASEID>C1</CASEID>
      <CASEBA>MEDICAID</CASEBA>
      <ISSUEID>I1</ISSUEID>
      <ISSUEBA>MEDICAID</ISSUEBA>
      <OBJECTID>extra</OBJECTID>
   </row>
   <row>
      <CASEID>C2</CASEID>
      <CASEBA>MEDICAID</CASEBA>
      <ISSUEID>I3</ISSUEID>
      <ISSUEBA>MEDICAID</ISSUEBA>
      <OBJECTID>3</OBJECTID>
   </row>
</results>

我有上述XML转换到使用XSLT通过按照下面条件简单之一:

1)首先目标是将所有的<CASEID>的,它们的值是新的下相同<CASE>沿着标签<CASEBA>节点。

例如:

<CASE>
   <CASEID>C1</CASEID>
   <CASEBA>MEDICAID</CASEBA>
</CASE>

2)列出了所有的<ISSUEID> <ISSUEBA><CASEID>的是在不同的相等<row>的和新的标记下移动它们<ISSUE>最近创建的内<CASE>标记。

例如:

 <CASE>
     <CASEID>C1</CASEID>
     <CASEBA>MEDICAID</CASEBA>
     <ISSUE>
        <ISSUEID>I1</ISSUEID>
        <ISSUEBA>MEDICAID</ISSUEBA>
     </ISSUE>
     <ISSUE>
        <ISSUEID>I2</ISSUEID>
        <ISSUEBA>MEDICAID</ISSUEBA>
     </ISSUE>
  </CASE>

3)列出了所有的<OBJECTID>的其<ISSUEID>的是在不同的相等<row>的和在移动它们的新<SOURCE>内标签<ISSUE>标签,这将是肯定的下<CASE> 。 例如:

<CASE>
         <CASEID>C1</CASEID>
         <CASEBA>MEDICAID</CASEBA>
         <ISSUE>
            <ISSUEID>I1</ISSUEID>
            <ISSUEBA>MEDICAID</ISSUEBA>
            <SOURCE>
               <OBJECTID>1</OBJECTID>
            </SOURCE>
            <SOURCE>
               <OBJECTID>extra</OBJECTID>
            </SOURCE>
         </ISSUE>
         <ISSUE>
            <ISSUEID>I2</ISSUEID>
            <ISSUEBA>MEDICAID</ISSUEBA>
            <SOURCE>
               <OBJECTID>2</OBJECTID>
            </SOURCE>
         </ISSUE>
      </CASE>

最终输出的XML应该如下:

<results>
   <CASE>
      <CASEID>C1</CASEID>
      <CASEBA>MEDICAID</CASEBA>
      <ISSUE>
         <ISSUEID>I1</ISSUEID>
         <ISSUEBA>MEDICAID</ISSUEBA>
         <SOURCE>
            <OBJECTID>1</OBJECTID>
         </SOURCE>
         <SOURCE>
            <OBJECTID>extra</OBJECTID>
         </SOURCE>
      </ISSUE>
      <ISSUE>
         <ISSUEID>I2</ISSUEID>
         <ISSUEBA>MEDICAID</ISSUEBA>
         <SOURCE>
            <OBJECTID>2</OBJECTID>
         </SOURCE>
      </ISSUE>
   </CASE>
   <CASE>
      <CASEID>C2</CASEID>
      <CASEBA>MEDICAID</CASEBA>
      <ISSUE>
         <ISSUEID>I3</ISSUEID>
         <ISSUEBA>MEDICAID</ISSUEBA>
         <SOURCE>
            <OBJECTID>3</OBJECTID>
         </SOURCE>
      </ISSUE>
   </CASE>
</results>

请原谅我,如果我不好好解释一下我的要求。 请不要问我,如果你需要任何额外的信息。 如果有人可以帮助我走出这将是真正伟大的。

Answer 1:

使用XSLT 1你必须使用一个名为“Muenchian分组的”和事技术将得到一个有点复杂。 幸运的是使用XSLT 2可以使用<xsl:for-each-group>元件和current-group()函数。 下面的样式表生成您要求给定的输入准确的输出:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:output method="xml" indent="yes" />

    <xsl:key name="caseID" match="row" use="CASEID" />

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/results">
        <results>
            <xsl:for-each-group select="row" group-by="CASEID">
                <xsl:call-template name="handleCase" />
            </xsl:for-each-group>
        </results>
    </xsl:template>

    <xsl:template name="handleCase"> 
        <CASE>
            <xsl:copy-of select="CASEID" />
            <xsl:copy-of select="CASEBA" />
            <xsl:for-each-group select="current-group()" group-by="ISSUEID">
                <xsl:call-template name="handleIssue" />
            </xsl:for-each-group>
        </CASE>
    </xsl:template>

    <xsl:template name="handleIssue"> 
        <ISSUE>
            <xsl:copy-of select="ISSUEID" />
            <xsl:copy-of select="ISSUEBA" />
            <xsl:apply-templates select="current-group()/OBJECTID" />
        </ISSUE>
    </xsl:template>

    <xsl:template match="OBJECTID">
        <SOURCE>
            <xsl:copy-of select="." />
        </SOURCE>
    </xsl:template>

</xsl:transform>

你可以窝整个事情,但要保持它的可读性,我把它分成几个命名模板。 幸运的调用另一个模板时,当前组上下文被保留,因此您可以在该组中另一组。



文章来源: Transforming xml based on node values
标签: xslt