XSLT - 基于连续行上的隐式链接进行合并,排序,重复数据删除,排序和重新编号

时间:2017-03-15 18:22:36

标签: xslt xslt-1.0

我遇到了无法解决的XSLT问题。

我有以下XML XML片段:

<xsl:key name="citedJpcc" match="memberP//patent/patentCitations/fieldOfSearch/classificationJp/jppc" use="."/>

<!-- The Wrapper-->
<xsl:template match="/">
..
..
<fieldOfSearch>    
<xsl:if test="patent/patentCitations/fieldOfSearch/classificationJp
  <classificationJp tsip:action="replace">
    <xsl:variable name="classificationJppc">  -- variable holds subtree
     <xsl:for-each select="patent/patentCitations/fieldOfSearch/classificationJp/jppc">
     <xsl:sort order="descending" select="@*"/> -- Sorts on attributes
     <xsl:if test="generate-id(.) = generate-id(key('citedJpcc', .))"> -- dedupes
     <xsl:element name="jppc">
       <xsl:if test="@tsip:rangeFrom">
        <xsl:attribute name="tsip:rangeFrom">
          <xsl:value-of select="@tsip:rangeFrom"/>
        </xsl:attribute>
       </xsl:if>
       <xsl:if test="@tsip:rangeTo">
         <xsl:attribute name="tsip:rangeTo">
           <xsl:value-of select="@tsip:rangeTo"/>
         </xsl:attribute>
       </xsl:if>
       <xsl:copy-of select="text()"/>
     </xsl:element>
   </xsl:if>
  </xsl:for-each>
 </xsl:variable>
 <xsl:copy-of select="$classificationJppc"/>
 </fieldOfSearch>
 ..
 ..

我需要做的是基于tsip:rangeFrom和tsip:rangeTo属性值进行合并,重复数据删除,排序和重新编号!

使用以下代码段:

<fieldOfSearch>
<classificationJp tsip:action="replace">
 <jppc tsip:rangeFrom="3">A61C-5/10</jppc>
 <jppc tsip:rangeTo="3">A61C-5/12</jppc>
 <jppc tsip:rangeFrom="2">A61C-8/00</jppc>
 <jppc tsip:rangeTo="2">A61C-13/38</jppc>
 <jppc tsip:rangeFrom="1">A61C-5/18</jppc>
 <jppc tsip:rangeTo="1">A61C-5/120</jppc>
 <jppc tsip:rangeFrom="1">A61C-5/15</jppc>
 <jppc tsip:rangeTo="1">A61C-5/16</jppc>
 <jppc>A61C-13/39</jppc>
 <jppc>A61C-13/40</jppc>
</classificationJp>
</fieldOfSearch>

这会进行合并,排序和重复数据删除:

<fieldOfSearch>
<classificationJp tsip:action="replace">
 <jppc tsip:rangeFrom="1">A61C-5/10</jppc>
 <jppc tsip:rangeTo="1">A61C-5/12</jppc>
 <jppc tsip:rangeFrom="2">A61C-8/00</jppc>
 <jppc tsip:rangeTo="2">A61C-13/38</jppc>
 <jppc tsip:rangeFrom="3">A61C-5/18</jppc>
 <jppc tsip:rangeTo="3">A61C-5/120</jppc>
 <jppc tsip:rangeFrom="4">A61C-5/15</jppc>
 <jppc tsip:rangeTo="4">A61C-5/16</jppc>
 <jppc>A61C-13/39</jppc>
 <jppc>A61C-13/40</jppc>
</classificationJp>
</fieldOfSearch>

具有tsip的行:rangeFrom和tsip:rangeTo通过具有相同的属性值隐式链接在一起!

我还需要做的是重新编号保持隐式链接的行,以便:

{{1}}

但我不知道该怎么做。

请帮忙!

1 个答案:

答案 0 :(得分:1)

这是一个可以适应您需求的最小化示例:

<强> XML

<memberP xmlns:tsip="http://example.com/tsip">
  <patent>
    <patentCitations tsip:action="replace">
      <fieldOfSearch>
        <classificationJp tsip:action="replace">
          <jppc tsip:rangeFrom="1">A61C-5/18</jppc>
          <jppc tsip:rangeTo="1">A61C-5/120</jppc>
          <jppc tsip:rangeFrom="2">A61C-8/00</jppc>
          <jppc tsip:rangeTo="2">A61C-13/38</jppc>
          <jppc tsip:rangeFrom="3">A61C-5/10</jppc>
          <jppc tsip:rangeTo="3">A61C-5/12</jppc>
          <jppc>A61C-13/39</jppc>
          <jppc>A61C-13/40</jppc>
          <jppc>A61C-13/39</jppc>
        </classificationJp>
      </fieldOfSearch>
    </patentCitations>
  </patent>
  <patent>
    <patentCitations tsip:action="replace">
      <fieldOfSearch>
        <classificationJp tsip:action="replace">
          <jppc tsip:rangeFrom="1">A61C-5/15</jppc>
          <jppc tsip:rangeTo="1">A61C-5/16</jppc>
          <jppc>A61C-13/39</jppc>
          <jppc>A61C-13/40</jppc>
          <jppc>A61C-13/39</jppc>
        </classificationJp>
      </fieldOfSearch>
    </patentCitations>
  </patent>
</memberP>

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tsip="http://example.com/tsip">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="citedJpcc" match="jppc" use="."/>

<xsl:template match="memberP">
    <fieldOfSearch>    
        <classificationJp tsip:action="replace">
            <!-- for each distinct jppc  -->
            <xsl:for-each select="patent/patentCitations/fieldOfSearch/classificationJp/jppc[generate-id()=generate-id(key('citedJpcc', .))]">
                <xsl:sort select="@tsip:rangeFrom | @tsip:rangeTo" data-type="number" order="descending"/>
                <xsl:copy>
                    <!-- renumber attributes  -->
                    <xsl:variable name="i" select="floor((position() + 1) div 2)" />
                    <xsl:for-each select="@tsip:rangeFrom | @tsip:rangeTo">
                        <xsl:attribute name="{name()}">
                            <xsl:value-of select="$i" />
                        </xsl:attribute>
                    </xsl:for-each>
                    <!-- copy content  -->
                    <xsl:value-of select="." />
                </xsl:copy>
            </xsl:for-each>
        </classificationJp>
    </fieldOfSearch>
</xsl:template>

</xsl:stylesheet>

<强>结果

<?xml version="1.0" encoding="UTF-8"?>
<fieldOfSearch xmlns:tsip="http://example.com/tsip">
   <classificationJp tsip:action="replace">
      <jppc tsip:rangeFrom="1">A61C-5/10</jppc>
      <jppc tsip:rangeTo="1">A61C-5/12</jppc>
      <jppc tsip:rangeFrom="2">A61C-8/00</jppc>
      <jppc tsip:rangeTo="2">A61C-13/38</jppc>
      <jppc tsip:rangeFrom="3">A61C-5/18</jppc>
      <jppc tsip:rangeTo="3">A61C-5/120</jppc>
      <jppc tsip:rangeFrom="4">A61C-5/15</jppc>
      <jppc tsip:rangeTo="4">A61C-5/16</jppc>
      <jppc>A61C-13/39</jppc>
      <jppc>A61C-13/40</jppc>
   </classificationJp>
</fieldOfSearch>

注意:我对您删除所有重复项感到有些困惑。由于巧合,远程值不可能具有有效重复,例如:

<jppc tsip:rangeFrom="1">A</jppc>
<jppc tsip:rangeTo="1">B</jppc>
<jppc tsip:rangeFrom="2">B</jppc>
<jppc tsip:rangeTo="2">C</jppc>

加了:

根据评论中的说明,我建议您尝试以下方法:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tsip="http://example.com/tsip"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="single" match="jppc[not(@tsip:rangeFrom or @tsip:rangeTo)]" use="."/>
<xsl:key name="range" match="range" use="concat(@from, '|', @to)"/>

<xsl:template match="memberP">
    <fieldOfSearch>    
        <classificationJp tsip:action="replace">
            <!-- handle ranges first -->
            <xsl:variable name="ranges">
                <xsl:for-each select="patent/patentCitations/fieldOfSearch/classificationJp/jppc[@tsip:rangeFrom]">
                    <range from="{.}" to="{following-sibling::jppc[1]}"/>
                </xsl:for-each>
            </xsl:variable>
            <!-- for each distinct range  -->
            <xsl:for-each select="exsl:node-set($ranges)/range[generate-id()=generate-id(key('range', concat(@from, '|', @to)))]">
                <!-- reconstruct and renumber  -->
                <jppc tsip:rangeFrom="{position()}">
                    <xsl:value-of select="@from"/>
                </jppc>
                <jppc tsip:rangeTo="{position()}">
                    <xsl:value-of select="@to"/>
                </jppc>
            </xsl:for-each>
            <!-- add singles (distinct only) -->
            <xsl:copy-of select="patent/patentCitations/fieldOfSearch/classificationJp/jppc[not(@tsip:rangeFrom or @tsip:rangeTo)][generate-id()=generate-id(key('single', .))]"/>
        </classificationJp>
    </fieldOfSearch>
</xsl:template>

</xsl:stylesheet>

应用于以下测试输入:

<强> XML

<memberP xmlns:tsip="http://example.com/tsip">
  <patent>
    <patentCitations tsip:action="replace">
      <fieldOfSearch>
        <classificationJp tsip:action="replace">
          <jppc tsip:rangeFrom="1">A</jppc>
          <jppc tsip:rangeTo="1">B</jppc>
          <jppc tsip:rangeFrom="2">B</jppc>
          <jppc tsip:rangeTo="2">C</jppc>
          <jppc tsip:rangeFrom="3">C</jppc>
          <jppc tsip:rangeTo="3">D</jppc>
          <jppc>A</jppc>
          <jppc>B</jppc>
          <jppc>C</jppc>
        </classificationJp>
      </fieldOfSearch>
    </patentCitations>
  </patent>
  <patent>
    <patentCitations tsip:action="replace">
      <fieldOfSearch>
        <classificationJp tsip:action="replace">
          <jppc tsip:rangeFrom="1">D</jppc>
          <jppc tsip:rangeTo="1">E</jppc>
          <jppc tsip:rangeFrom="2">B</jppc>
          <jppc tsip:rangeTo="2">C</jppc>
          <jppc>D</jppc>
          <jppc>B</jppc>
          <jppc>C</jppc>
        </classificationJp>
      </fieldOfSearch>
    </patentCitations>
  </patent>
</memberP>

结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<fieldOfSearch xmlns:tsip="http://example.com/tsip">
   <classificationJp tsip:action="replace">
      <jppc tsip:rangeFrom="1">A</jppc>
      <jppc tsip:rangeTo="1">B</jppc>
      <jppc tsip:rangeFrom="2">B</jppc>
      <jppc tsip:rangeTo="2">C</jppc>
      <jppc tsip:rangeFrom="3">C</jppc>
      <jppc tsip:rangeTo="3">D</jppc>
      <jppc tsip:rangeFrom="4">D</jppc>
      <jppc tsip:rangeTo="4">E</jppc>
      <jppc>A</jppc>
      <jppc>B</jppc>
      <jppc>C</jppc>
      <jppc>D</jppc>
   </classificationJp>
</fieldOfSearch>

请注意,这不会检测到部分重叠。