从每个特定用户ID中获取最大日期,不重复使用XSLT。

huangapple go评论48阅读模式
英文:

Get max date from each specific user ID without repeating IDs using XSLT

问题

您想提取每个用户的最大日期,并在结果中显示如下格式:

<?xml version="1.0" encoding="UTF-8"?>
<LastModified>15/3/2023</LastModified>
<User>5</User>

您已经创建了XSLT样式表,但遇到了重复的问题。要解决这个问题,您可以使用XSLT以一种更精细的方式处理数据,如下所示:

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

    <xsl:key name="user-key" match="Record" use="User"/>

    <xsl:template match="/root">
        <xsl:for-each select="Data/Record[generate-id() = generate-id(key('user-key', User)[1])]">
            <xsl:variable name="currentUser" select="User"/>
            <xsl:for-each select="key('user-key', $currentUser)">
                <xsl:sort select="concat(substring(LastModified, 7, 4), substring(LastModified, 4, 2), substring(LastModified, 1, 2))"
                        data-type="number" order="descending"/>
                <xsl:if test="position() = 1">
                    <LastModified>
                        <xsl:value-of select="LastModified"/>
                    </LastModified>
                    <User>
                        <xsl:value-of select="User"/>
                    </User>
                </xsl:if>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

这个XSLT样式表将为每个用户提取最大日期,而不会产生重复结果。

英文:

I have the following XML

&lt;?xml version=&#39;1.0&#39; encoding=&#39;UTF-8&#39;?&gt;
&lt;root&gt;
    &lt;Data&gt;
        &lt;Record&gt;
            &lt;User&gt;1&lt;/User&gt;
            &lt;LastModified&gt;1/1/2023&lt;/LastModified&gt;
            &lt;UniversityDegree&gt;University of Texas Bachelors&lt;/UniversityDegree&gt;
        &lt;/Record&gt;
        &lt;Record&gt;
            &lt;User&gt;1&lt;/User&gt;
            &lt;LastModified&gt;1/11/2023&lt;/LastModified&gt;
            &lt;UniversityDegree&gt;University of Missouri Masters&lt;/UniversityDegree&gt;
        &lt;/Record&gt;
        &lt;Record&gt;
            &lt;User&gt;2&lt;/User&gt;
            &lt;LastModified&gt;1/1/2024&lt;/LastModified&gt;
            &lt;UniversityDegree&gt;University of Texas Bachelors&lt;/UniversityDegree&gt;
        &lt;/Record&gt;
        &lt;Record&gt;
            &lt;User&gt;2&lt;/User&gt;
            &lt;LastModified&gt;1/12/2023&lt;/LastModified&gt;
            &lt;UniversityDegree&gt;University of Missouri Masters&lt;/UniversityDegree&gt;
        &lt;/Record&gt;
        &lt;Record&gt;
            &lt;User&gt;3&lt;/User&gt;
            &lt;LastModified&gt;5/7/2023&lt;/LastModified&gt;
            &lt;UniversityDegree&gt;University of Texas Bachelors&lt;/UniversityDegree&gt;
        &lt;/Record&gt;
        &lt;Record&gt;
            &lt;User&gt;3&lt;/User&gt;
            &lt;LastModified&gt;9/8/2023&lt;/LastModified&gt;
            &lt;UniversityDegree&gt;University of Missouri Masters&lt;/UniversityDegree&gt;
        &lt;/Record&gt;
        &lt;Record&gt;
            &lt;User&gt;4&lt;/User&gt;
            &lt;LastModified&gt;24/1/2023&lt;/LastModified&gt;
            &lt;UniversityDegree&gt;University of Texas Bachelors&lt;/UniversityDegree&gt;
        &lt;/Record&gt;
        &lt;Record&gt;
            &lt;User&gt;4&lt;/User&gt;
            &lt;LastModified&gt;28/9/2023&lt;/LastModified&gt;
            &lt;UniversityDegree&gt;University of Missouri Masters&lt;/UniversityDegree&gt;
        &lt;/Record&gt;
        &lt;Record&gt;
            &lt;User&gt;5&lt;/User&gt;
            &lt;LastModified&gt;15/3/2023&lt;/LastModified&gt;
            &lt;UniversityDegree&gt;University of Texas Bachelors&lt;/UniversityDegree&gt;
        &lt;/Record&gt;
        &lt;Record&gt;
            &lt;User&gt;5&lt;/User&gt;
            &lt;LastModified&gt;10/3/2023&lt;/LastModified&gt;
            &lt;UniversityDegree&gt;University of Missouri Masters&lt;/UniversityDegree&gt;
        &lt;/Record&gt;
    &lt;/Data&gt;
&lt;/root&gt;

And I need to extract the max date of each user, so for example out of use 5 the max date from 15/3/2023 and 10/3/2023 is 15/3/2023 and show it like this:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;LastModified&gt;15/3/2023&lt;/LastModified&gt;
&lt;User&gt;5&lt;/User&gt;

I've done the following,

&lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
   &lt;xsl:output method=&quot;xml&quot; indent=&quot;yes&quot;/&gt;
   &lt;xsl:template match=&quot;//root&quot;&gt;
      &lt;xsl:for-each select=&quot;//Record&quot;&gt;
         &lt;xsl:sort select=&quot;number(substring(LastModified, 7, 4))&quot; order=&quot;descending&quot;/&gt;
         &lt;xsl:sort select=&quot;number(substring(LastModified, 3, 2))&quot; order=&quot;descending&quot;/&gt;
         &lt;xsl:sort select=&quot;number(substring(LastModified, 1, 2))&quot; order=&quot;descending&quot;/&gt;
         
         
         &lt;xsl:if test=&quot;position() = 1&quot;&gt;
            &lt;xsl:copy-of select=&quot;LastModified&quot;/&gt;
            &lt;xsl:copy-of select=&quot;User&quot;/&gt;
            &lt;Source&gt;SF&lt;/Source&gt;
         &lt;/xsl:if&gt;

      &lt;/xsl:for-each&gt;
   &lt;/xsl:template&gt;
&lt;/xsl:stylesheet&gt;

Which returns,

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;LastModified&gt;1/1/2024&lt;/LastModified&gt;
&lt;User&gt;2&lt;/User&gt;
&lt;Source&gt;SF&lt;/Source&gt;

But it only returns the first sorted record due to the position 1 if. I would need to get the max date of each of the users without having duplicates. If I remove the IF condition, I get everything sorted but Users are repeated,

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;LastModified&gt;1/1/2024&lt;/LastModified&gt;
&lt;User&gt;2&lt;/User&gt;
&lt;Source&gt;SF&lt;/Source&gt;
&lt;LastModified&gt;1/12/2023&lt;/LastModified&gt;
&lt;User&gt;2&lt;/User&gt;
&lt;Source&gt;SF&lt;/Source&gt;
&lt;LastModified&gt;1/11/2023&lt;/LastModified&gt;
&lt;User&gt;1&lt;/User&gt;
&lt;Source&gt;SF&lt;/Source&gt;
&lt;LastModified&gt;28/9/2023&lt;/LastModified&gt;
&lt;User&gt;4&lt;/User&gt;
&lt;Source&gt;SF&lt;/Source&gt;
&lt;LastModified&gt;24/1/2023&lt;/LastModified&gt;
&lt;User&gt;4&lt;/User&gt;
&lt;Source&gt;SF&lt;/Source&gt;
&lt;LastModified&gt;15/3/2023&lt;/LastModified&gt;
&lt;User&gt;5&lt;/User&gt;
&lt;Source&gt;SF&lt;/Source&gt;
&lt;LastModified&gt;10/3/2023&lt;/LastModified&gt;
&lt;User&gt;5&lt;/User&gt;
&lt;Source&gt;SF&lt;/Source&gt;
&lt;LastModified&gt;1/1/2023&lt;/LastModified&gt;
&lt;User&gt;1&lt;/User&gt;
&lt;Source&gt;SF&lt;/Source&gt;
&lt;LastModified&gt;5/7/2023&lt;/LastModified&gt;
&lt;User&gt;3&lt;/User&gt;
&lt;Source&gt;SF&lt;/Source&gt;
&lt;LastModified&gt;9/8/2023&lt;/LastModified&gt;
&lt;User&gt;3&lt;/User&gt;
&lt;Source&gt;SF&lt;/Source&gt;

答案1

得分: 0

以下是您提供的代码的翻译:

尝试使用如下的方式:

**XSLT 2.0**

    <xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="/root">
    	<result>
    		<xsl:for-each-group select="Data/Record" group-by="User">
    			<user>
    				<xsl:for-each select="current-group()">
    					<xsl:sort select="tokenize(LastModified, '/')" data-type="number" order="descending"/>
    					<xsl:sort select="tokenize(LastModified, '/')[2]" data-type="number" order="descending"/>
    					<xsl:sort select="tokenize(LastModified, '/')[1]" data-type="number" order="descending"/>
    					<xsl:if test="position() = 1">
    						<xsl:copy-of select="LastModified, User"/>
    						<Source>SF</Source>
    					</xsl:if>
    				</xsl:for-each>
    			</user>
     		</xsl:for-each-group>
    	</result>
    </xsl:template>
    
    </xsl:stylesheet>

请注意:这个翻译是提供给您参考的代码的XML表示,未进行详细测试。

英文:

Try perhaps something like:

XSLT 2.0

&lt;xsl:stylesheet version=&quot;2.0&quot; 
xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
&lt;xsl:output method=&quot;xml&quot; version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; indent=&quot;yes&quot;/&gt;

&lt;xsl:template match=&quot;/root&quot;&gt;
	&lt;result&gt;
		&lt;xsl:for-each-group select=&quot;Data/Record&quot; group-by=&quot;User&quot;&gt;
			&lt;user&gt;
				&lt;xsl:for-each select=&quot;current-group()&quot;&gt;
					&lt;xsl:sort select=&quot;tokenize(LastModified, &#39;/&#39;)[3]&quot; data-type=&quot;number&quot; order=&quot;descending&quot;/&gt;
					&lt;xsl:sort select=&quot;tokenize(LastModified, &#39;/&#39;)[2]&quot; data-type=&quot;number&quot; order=&quot;descending&quot;/&gt;
					&lt;xsl:sort select=&quot;tokenize(LastModified, &#39;/&#39;)[1]&quot; data-type=&quot;number&quot; order=&quot;descending&quot;/&gt;
					&lt;xsl:if test=&quot;position() = 1&quot;&gt;
						&lt;xsl:copy-of select=&quot;LastModified, User&quot;/&gt;
						&lt;Source&gt;SF&lt;/Source&gt;
					&lt;/xsl:if&gt;
				&lt;/xsl:for-each&gt;
			&lt;/user&gt;
 		&lt;/xsl:for-each-group&gt;
	&lt;/result&gt;
&lt;/xsl:template&gt;

&lt;/xsl:stylesheet&gt;

Caveat: not tested very thoroughly.

答案2

得分: 0

以下是一个稍微不同的方法,不一定更好,但它利用了更多的XSLT 2.0特性:

XSLT 2.0

&lt;xsl:stylesheet version=&quot;2.0&quot;
xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;
xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot;
xmlns:mf=&quot;http://www.example.com/mf&quot;
exclude-result-prefixes=&quot;xs mf&quot;&gt;
&lt;xsl:output method=&quot;xml&quot; version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; indent=&quot;yes&quot;/&gt;

&lt;xsl:template match=&quot;/root&quot;&gt;
	&lt;result&gt;
		&lt;xsl:for-each-group select=&quot;Data/Record&quot; group-by=&quot;User&quot;&gt;
			&lt;user&gt;
				&lt;LastModified&gt;
					&lt;xsl:value-of select=&quot;format-date(max(current-group()/LastModified/mf:reformat-date(.)), &#39;[D]/[M]/[Y]&#39;)&quot;/&gt;
				&lt;/LastModified&gt;
				&lt;xsl:copy-of select=&quot;User&quot;/&gt;
				&lt;Source&gt;SF&lt;/Source&gt;
			&lt;/user&gt;
 		&lt;/xsl:for-each-group&gt;
	&lt;/result&gt;
&lt;/xsl:template&gt;

&lt;xsl:function name=&quot;mf:reformat-date&quot; as=&quot;xs:date&quot;&gt;
	&lt;!-- 期望的输入格式: d/m/y --&gt;
	&lt;xsl:param name=&quot;date&quot;/&gt; 
	&lt;xsl:variable name=&quot;components&quot; select=&quot;for $t in tokenize($date, &#39;/&#39;) return xs:integer($t)&quot; /&gt;
	&lt;xsl:value-of select=&quot;format-number($components[3], &#39;0000&#39;), format-number($components[2], &#39;00&#39;), format-number($components[1], &#39;00&#39;)&quot; separator=&quot;-&quot;/&gt;
&lt;/xsl:function&gt;

&lt;/xsl:stylesheet&gt;
英文:

Here is a somewhat different approach that's not necessarily better, but it takes advantage of more XSLT 2.0 features:

XSLT 2.0

&lt;xsl:stylesheet version=&quot;2.0&quot;
xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;
xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot;
xmlns:mf=&quot;http://www.example.com/mf&quot;
exclude-result-prefixes=&quot;xs mf&quot;&gt;
&lt;xsl:output method=&quot;xml&quot; version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; indent=&quot;yes&quot;/&gt;

&lt;xsl:template match=&quot;/root&quot;&gt;
	&lt;result&gt;
		&lt;xsl:for-each-group select=&quot;Data/Record&quot; group-by=&quot;User&quot;&gt;
			&lt;user&gt;
				&lt;LastModified&gt;
					&lt;xsl:value-of select=&quot;format-date(max(current-group()/LastModified/mf:reformat-date(.)), &#39;[D]/[M]/[Y]&#39;)&quot;/&gt;
				&lt;/LastModified&gt;
				&lt;xsl:copy-of select=&quot;User&quot;/&gt;
				&lt;Source&gt;SF&lt;/Source&gt;
			&lt;/user&gt;
 		&lt;/xsl:for-each-group&gt;
	&lt;/result&gt;
&lt;/xsl:template&gt;

&lt;xsl:function name=&quot;mf:reformat-date&quot; as=&quot;xs:date&quot;&gt;
	&lt;!-- expected input format: d/m/y --&gt;
	&lt;xsl:param name=&quot;date&quot;/&gt; 
	&lt;xsl:variable name=&quot;components&quot; select=&quot;for $t in tokenize($date, &#39;/&#39;) return xs:integer($t)&quot; /&gt;
	&lt;xsl:value-of select=&quot;format-number($components[3], &#39;0000&#39;), format-number($components[2], &#39;00&#39;), format-number($components[1], &#39;00&#39;)&quot; separator=&quot;-&quot;/&gt;
&lt;/xsl:function&gt;

&lt;/xsl:stylesheet&gt;

huangapple
  • 本文由 发表于 2023年2月14日 01:40:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75439417.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定