gpt4 book ai didi

xslt - 在同一节点内按 ID 排序,然后按时间戳排序

转载 作者:行者123 更新时间:2023-12-04 15:36:21 26 4
gpt4 key购买 nike

关于使用 XSL 1.0(并且只有 1.0 - 我正在使用 .Net Parser)进行排序,我有一个非常特殊的问题。

这是我的 xml :

<Root>
....
<PatientsPN>
<Patient>
<ID>1</ID>
<TimeStamp>20111208165819</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>4</ID>
<TimeStamp>20111208165910</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny4</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>4</ID>
<TimeStamp>20111208165902</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>FannyMOI</PrenomPatient>
<Sexe>M</Sexe>
</Patient>
<Patient>
<ID>2</ID>
<TimeStamp>20111208170000</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>FannyMOI</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>2</ID>
<TimeStamp>20111208165819</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>2</ID>
<TimeStamp>20111208170050</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Cmoi2</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>3</ID>
<TimeStamp>20111208165829</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Jesuis3</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
</PatientsPN>
...
</Root>

我想首先按 ID 对我的 PatientsNP 进行排序,然后采用每个 ID 的较高时间戳。
我的输出:
<Root>
<PatientsPN>
<Patient>
<ID>1</ID>
<TimeStamp>20111208165819</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>2</ID>
<TimeStamp>20111208170050</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Cmoi2</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>3</ID>
<TimeStamp>20111208165829</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Jesuis3</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>4</ID>
<TimeStamp>20111208165910</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny4</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
</PatientsPN>
</Root>

首先,我尝试按 ID 对列表进行排序,然后解析每个节点并使用 Xpath 提取更高的时间戳,但这不起作用。它不断重复其他节点。

还尝试了 Muench 排序方法,但我无法使用更通用的方法使其正常工作。

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

<xsl:template match="/">
<Root>
<xsl:apply-templates/>
</Root>
</xsl:template>

<xsl:template match="/Root/*">
<xsl:for-each select=".">
<xsl:choose>
<xsl:when test="substring(name(), (string-length(name()) - string-length($mark)) + 1) = $mark">
<!-- Search for an ID tag -->
<xsl:copy>
<xsl:if test="node()/ID">
<xsl:for-each select="node()">
<xsl:sort select="ID" order="ascending" />
<!-- So far everything I've done here failed -->
<xsl:for-each select=".[ID = '1']">
<xsl:copy>
<xsl:copy-of select="node()[not(number(TimeStamp) &lt; (preceding-sibling::node()/TimeStamp | following-sibling::node()/TimeStamp))]"/>
</xsl:copy>
</xsl:for-each>
<!-- This is just an example, I don't want to have ID = 1 and ID = 2 -->
</xsl:for-each>
</xsl:if>

<xsl:if test="not(node()/ID)">
<xsl:copy-of select="node()[not(number(TimeStamp) &lt; (preceding-sibling::node()/TimeStamp | following-sibling::node()/TimeStamp))]"/>
</xsl:if>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

我希望我说清楚了。
在此先感谢您为我提供的所有帮助!

编辑:

我真的很抱歉我应该提到我想让它尽可能通用。在我的示例中,我谈论的是PatientsPN,但我真正想做的是匹配每个以PN 结尾的PARENT 节点(因此以XSL 1.0 的山寨版结尾)。

不管怎样,你真的很了不起,我不能指望你能得到更多。谢谢 !

解决方案
在改造了Dimitre给出的解决方案后,我想出了这个XSL:
<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kPatById" match="*['PN' = substring(name(), string-length(name()) -1)]/*"
use="concat(generate-id(..), '|', ID)"/>

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

<xsl:template match="*['PN' = substring(name(), string-length(name()) -1)]">
<xsl:copy>
<xsl:apply-templates select="node()">
<xsl:sort select="ID" data-type="number"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>

<xsl:template match="*['PN' = substring(name(), string-length(name()) -1)]/node()[TimeStamp &lt; key('kPatById', concat(generate-id(..), '|', ID))/TimeStamp]"/>
</xsl:stylesheet>

它出色地完成了这项工作,它允许我拥有多个要处理和排序的父节点。

最佳答案

可以这么简单 :

一、XSLT 1.0解决方案 :

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="kPatById" match=
"*['PN' = substring(name(), string-length(name()) -1)]/Patient"
use="concat(generate-id(..), '|', ID)"/>

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

<xsl:template match=
"*['PN' = substring(name(), string-length(name()) -1)]">
<xsl:apply-templates select="Patient">
<xsl:sort select="ID" data-type="number"/>
</xsl:apply-templates>
</xsl:template>

<xsl:template match=
"*['PN' = substring(name(), string-length(name()) -1)]
/Patient
[TimeStamp &lt; key('kPatById', concat(generate-id(..), '|', ID))/TimeStamp]
"/>
</xsl:stylesheet>

应用于提供的 XML 文档时 :
<Root>
....
<PatientsPN>
<Patient>
<ID>1</ID>
<TimeStamp>20111208165819</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>4</ID>
<TimeStamp>20111208165910</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny4</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>4</ID>
<TimeStamp>20111208165902</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>FannyMOI</PrenomPatient>
<Sexe>M</Sexe>
</Patient>
<Patient>
<ID>2</ID>
<TimeStamp>20111208170000</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>FannyMOI</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>2</ID>
<TimeStamp>20111208165819</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>2</ID>
<TimeStamp>20111208170050</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Cmoi2</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>3</ID>
<TimeStamp>20111208165829</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Jesuis3</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
</PatientsPN>
...
</Root>

产生了想要的、正确的结果 :
<Root>
....
<Patient>
<ID>1</ID>
<TimeStamp>20111208165819</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>2</ID>
<TimeStamp>20111208170050</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Cmoi2</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>3</ID>
<TimeStamp>20111208165829</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Jesuis3</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>4</ID>
<TimeStamp>20111208165910</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny4</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
...
</Root>

说明 :
  • 匹配名称以 "PN" 结尾的任何元素-- 使用 substring() 的组合和 string-length() .
  • 覆盖 identity rule .
  • 排序,但 不使用任何 Muenchian 分组 .
  • 使用 key 获取同一患者下的所有记录xxxPN parent 。
  • “简单”最大值(无排序)。
  • 正确的模式匹配以排除任何不需要的记录。


  • 二、 XSLT 2.0 解决方案 :

    我认为最好的 XSLT 2.0 解决方案与上面的 XSLT 1.0 解决方案几乎相同,但可能更有效:
    <xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:key name="kPatById" match="*[ends-with(name(),'PN')]/Patient"
    use="concat(generate-id(..), '|', ID)"/>

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

    <xsl:template match="*[ends-with(name(),'PN')]">
    <xsl:apply-templates select="Patient">
    <xsl:sort select="ID" data-type="number"/>
    </xsl:apply-templates>
    </xsl:template>

    <xsl:template match=
    "*[ends-with(name(),'PN')]
    /Patient
    [number(TimeStamp)
    lt
    max((key('kPatById', concat(generate-id(..), '|', ID))
    /TimeStamp/xs:double(.)))
    ]"/>
    </xsl:stylesheet>

    关于xslt - 在同一节点内按 ID 排序,然后按时间戳排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8488643/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com