简体   繁体   中英

XSLT 1.0 Copy attribute of each matching element

So here is my input XML:

    <?xml version="1.0" encoding="utf-8"?>
    <modifs>
  <modif id="229818">
<avant num_words="1">dans</avant>
<apres num_words="1">par</apres></modif>
  <modif id="196216">
<avant num_words="1">dans</avant>
<apres num_words="1">parmi</apres></modif>
  <modif id="2162">
<avant num_words="1">dans</avant>
<apres num_words="1">pour</apres></modif>
  <modif id="9273">
<avant num_words="1">dans</avant>
<apres num_words="1">pour</apres></modif>
</modifs>

Basically what I want to do is to copy everything, except for duplicate content. For the said duplicate content, I'd like to group the different ids under the first element of the same kind. The result I would like to get would be something like this:

 <?xml version="1.0" encoding="utf-8"?>
    <modifs>
  <modif id="229818">
<avant num_words="1">dans</avant>
<apres num_words="1">par</apres></modif>
  <modif id="196216">
<avant num_words="1">dans</avant>
<apres num_words="1">parmi</apres></modif>
  <modif id="2162">
<extra_id="9273">
<avant num_words="1">dans</avant>
<apres num_words="1">pour</apres></modif>
</modifs>

And here is my attempt so far: I'm trying to check first if there has already been a duplicate (if so, do nothing), then if there are duplicates afterwards. If there are any, get their id attribute and copy it. (That's what I don't know how to do). Finally if there are no duplicates, just copy the element.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" indent="yes"/>

  <xsl:template match="modifs">
    <xsl:for-each select="./modif">
      <xsl:choose>
        <xsl:when test="./avant=preceding-sibling::modif/avant">
          <xsl:if test="./apres=preceding-sibling::modif/apres">
          </xsl:if>
        </xsl:when>
        <xsl:when test="./avant=following-sibling::modif/avant">
          <xsl:if test="./apres=following-sibling::modif/apres">
            <xsl:element name="modif">
            <xsl:for-each select="following-sibling::modif/@id=./@id">
              <xsl:value-of select="."/>            
          </xsl:for-each>
              <xsl:copy-of select="."/>
              </xsl:element>
          </xsl:if>
        </xsl:when>
        <xsl:otherwise>
          <xsl:copy-of select="."/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet> 

I don't know if my question is clear, if not or if there is any other problem with it (or with my english) please tell me I'll happily change it.

Thanks

You may try this Muenchian grouping :

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

        <xsl:key name="kmodif" match="modif" use="concat(avant, '|', apres)"/>

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

        <xsl:template match="/modifs">
            <xsl:copy>
                <xsl:for-each
                    select="modif[generate-id() = generate-id(key('kmodif', concat(avant, '|', apres))[1])]" >
                    <!-- group -->
                    <xsl:copy>
                        <xsl:apply-templates select="@*" />

                        <xsl:for-each
                            select="key('kmodif', concat(avant, '|', apres))[position() != 1]" >
                            <!-- group member-->
                            <extra id="{@id}" />
                        </xsl:for-each>
                        <xsl:apply-templates select="*" />
                    </xsl:copy>
                    </xsl:for-each>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>

With the following output:

        <modifs>
            <modif id="229818">
                <avant num_words="1">dans</avant>
                <apres num_words="1">par</apres>
            </modif>
            <modif id="196216">
                <avant num_words="1">dans</avant>
                <apres num_words="1">parmi</apres>
            </modif>
            <modif id="2162">
                <extra id="9273"/>
                <avant num_words="1">dans</avant>
                <apres num_words="1">pour</apres>
            </modif>
        </modifs>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM