简体   繁体   中英

How do I get the last child element attribute that doesn't match a parent element attribute (xslt)?

I am trying to get the last child element for a parent that does not have an attribute that matches one of the parent element's attributes? I have been working on this for a while and so far have come up empty handed.

I can easily get the last element and look to see if it's attribute matches. If it doesn't, I can check last-1, but how do I do this recursively or with a built in function?

In the example below, the parent element (MainRecord) has 3 attributes (Data1, Data2, Data3) that might be there or might be null. The child element has one data attribute that may or may not be one of the parent data attributes.

So for RecordNumber=1, I need Cloud because Rainbow is in the parent. Record 3 goes all the way up to Sunshine because Flower, Cloud and Rainbow are all in the parent.

XML File:

<MainRecord Data1="" Data2="" Data3="Rainbow" RecordNumber="1">
    <AuditRecord Data="Sky" SomomethingElse="Hi"/>
    <AuditRecord Data="Sunshine" SomomethingElse="Yo"/>
    <AuditRecord Data="Flower" SomomethingElse="Do"/>
    <AuditRecord Data="Cloud" SomomethingElse="Re"/>
    <AuditRecord Data="Rainbow" SomomethingElse="Mi"/>
</MainRecord>
<MainRecord Data1="" Data2="Cloud" Data3="Rainbow" RecordNumber="2">
    <AuditRecord Data="Sky" SomomethingElse="Hi"/>
    <AuditRecord Data="Sunshine" SomomethingElse="Yo"/>
    <AuditRecord Data="Flower" SomomethingElse="Do"/>
    <AuditRecord Data="Cloud" SomomethingElse="Re"/>
    <AuditRecord Data="Rainbow" SomomethingElse="Mi"/>
</MainRecord>
<MainRecord Data1="Flower" Data2="Cloud" Data3="Rainbow" RecordNumber="3">
    <AuditRecord Data="Sky" SomomethingElse="Hi"/>
    <AuditRecord Data="Sunshine" SomomethingElse="Yo"/>
    <AuditRecord Data="Flower" SomomethingElse="Do"/>
    <AuditRecord Data="Cloud" SomomethingElse="Re"/>
    <AuditRecord Data="Rainbow" SomomethingElse="Mi"/>
</MainRecord>
<MainRecord Data1="Cloud" Data2="Flower" Data3="" RecordNumber="4">
    <AuditRecord Data="Sky" SomomethingElse="Hi"/>
    <AuditRecord Data="Sunshine" SomomethingElse="Yo"/>
    <AuditRecord Data="Flower" SomomethingElse="Do"/>
    <AuditRecord Data="Cloud" SomomethingElse="Re"/>
    <AuditRecord Data="Rainbow" SomomethingElse="Mi"/>
</MainRecord>
<MainRecord Data1="" Data2="" Data3="" RecordNumber="5">
    <AuditRecord Data="Sky" SomomethingElse="Hi"/>
    <AuditRecord Data="Sunshine" SomomethingElse="Yo"/>
    <AuditRecord Data="Flower" SomomethingElse="Do"/>
    <AuditRecord Data="Cloud" SomomethingElse="Re"/>
    <AuditRecord Data="Rainbow" SomomethingElse="Mi"/>
</MainRecord>

Desired output after transformation:

<MainRecord RecordNumber="1" MaxData="Cloud"/>
<MainRecord RecordNumber="2" MaxData="Flower"/>
<MainRecord RecordNumber="3" MaxData="Sunshine"/>
<MainRecord RecordNumber="4" MaxData="Rainbow"/>
<MainRecord RecordNumber="5" MaxData="Rainbow"/>

Here is my playing around with this. The variable for maxData doesn't work and I am sure it isn't the right way to do this, but I'm stuck.

<MainRecords>
    <xsl:for-each select="MainRecord">
        <xsl:attribute name="RecordNumber"><xsl:value-of select="@RecordNumber"/></xsl:attribute>
        <xsl:variable name="maxData"/>
        <xsl:for-each select="AuditRecord">
            <xsl:if test="not(@Data=@Data1) and not(@Data=@Data2) and not(@Data=@Data3)">
                <xsl:variable name="maxDate"><xsl:value-of select="@Data"/></xsl:variable>
            </xsl:if>
        </xsl:for-each>

        <xsl:attribute name="Count"><xsl:value-of select="count(AuditRecord)"/></xsl:attribute>
        <xsl:attribute name="LastDataThatDoesntMatch"><xsl:value-of select="$maxDate"/></xsl:attribute>
        <xsl:attribute name="Last"><xsl:value-of select="ItemAudit[last()]/@Date"/></xsl:attribute>
        <xsl:attribute name="2ndLast"><xsl:value-of select="ItemAudit[last()-1]/@Date"/></xsl:attribute>
        <xsl:attribute name="3rdLast"><xsl:value-of select="ItemAudit[last()-2]/@Date"/></xsl:attribute>
        <xsl:attribute name="4thLast"><xsl:value-of select="ItemAudit[last()-3]/@Date"/></xsl:attribute>
    </xsl:for-each>
</MainRecords>

I appreciate any help. This is obviously not the actual data- just a simple version of the problem that has no proprietary data. Not a school project and it's my first time using xslt in a project, so this is a bit foreign to me.

I think you simply want

  <xsl:template match="MainRecord">
      <MainRecord RecordNumber="{@RecordNumber}" MaxData="{AuditRecord[not(@Data = current()/@*[starts-with(local-name(), 'Data')])][last()]/@Data}"/>
  </xsl:template>

https://xsltfiddle.liberty-development.net/bnnZXc

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