gpt4 book ai didi

xml - XSLT - 分析以下连续节点

转载 作者:数据小太阳 更新时间:2023-10-29 02:34:09 26 4
gpt4 key购买 nike

我有一个这样的xml,

<doc>
<para>texttext<page>1</page>texttext<page>1</page>texttext</para>
<para>texttext<page>1</page><page>2</page>texttext</para>
<para>texttext<page>1</page><page>2</page><page>3</page>texttext<page>4</page><page>5</page><page>6</page>texttext</para>
<para>texttext<page>1</page><page>2</page><page>3</page><page>4</page>texttext</para>
</doc>

我需要转换 <page>节点到 <link>使用 xsl 转换并需要考虑以下规则,

  • 如果只有一个<page>节点出现(未跟随任何页面节点)它只是转换为 <link>
  • 如果两个<page>连续放置的节点(上面示例中的场景 2)必须在输出 <link> 之间添加 ','节点
  • 如果 3 个或更多 <page>连续放置的节点(上例中的场景3和4),只需添加以'-'分隔的页面节点的第一个和最后一个内容

所以,输出应该是这样的,

<doc>
<para>texttext<link>1</link>texttext<link>1</link>texttext</para>
<para>texttext<link>1</link>,<link>2</link>texttext</para>
<para>texttext<link>1</link>-<link>3</link>texttext<link>4</link>-<link>6</link>texttext</para>
<para>texttext<link>1</link>-<link>4</link>texttext</para>
</doc>

我写了下面的 xsl 来完成这个任务,

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

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

<xsl:template match="page[following-sibling::node()[1][self::page]]">
<link>
<xsl:apply-templates/>
</link>
<xsl:text>,</xsl:text>
<link>
<xsl:apply-templates select="following-sibling::*[1]"/>
</link>
</xsl:template>

<xsl:template match="page[following-sibling::node()[1][self::page]][following-sibling::node()[2][self::page]]">
<link>
<xsl:apply-templates/>
</link>
<xsl:text>-</xsl:text>
<link>
<xsl:apply-templates select="following-sibling::*[2]"/>
</link>
</xsl:template>

但是这个方法并没有起作用,因为当有 3 个连续的 <page> 时,它会添加 ','节点出现,如果有更多 <page>节点连续出现这种方法效率不高。

任何人都可以在 xslt 中建议一个好的方法来分析以下 sibling 形成 xslt 并完成此任务..

最佳答案

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

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

<xsl:template match="page[not(preceding-sibling::node()[1][self::page])]">
<xsl:variable name="pages" select="following-sibling::page[
preceding-sibling::node()[1][self::page]
and generate-id(current()) = generate-id(preceding-sibling::page[
not(preceding-sibling::node()[1][self::page])
][1])
]" />
<xsl:apply-templates select="." mode="link" />
<xsl:if test="count($pages) = 1">,</xsl:if>
<xsl:if test="count($pages) &gt; 1">-</xsl:if>
<xsl:apply-templates select="$pages[last()]" mode="link" />
</xsl:template>
<xsl:template match="page" />

<xsl:template match="page" mode="link">
<link>
<xsl:apply-templates select="@*|node()"/>
</link>
</xsl:template>
</xsl:transform>

结果

<doc>
<para>texttext<link>1</link>texttext<link>1</link>texttext</para>
<para>texttext<link>1</link>,<link>2</link>texttext</para>
<para>texttext<link>1</link>-<link>3</link>texttext<link>4</link>-<link>6</link>texttext</para>
<para>texttext<link>1</link>-<link>4</link>texttext</para>
</doc>

这里,

<xsl:template match="page[not(preceding-sibling::node()[1][self::page])]">

匹配任何<page>开始一个“范围”的连续页面。

选择连续范围的剩余页面有点棘手,但可以这样做:

  • 在所有以下同级页面中,选择那些
    • 本身紧接在 <page> 之前(即 “范围的一部分”)和
    • 最接近的前面<page>它本身不直接在另一个 <page> 之前(即 “最近的 <page> 开始一个范围”)与当前节点相同。

假设我们只处理 <page>在此模板中开始一个范围的节点,这相当于“是当前范围的一部分”

在 XPath 术语中,如上所示:

following-sibling::page[
preceding-sibling::node()[1][self::page]
and generate-id(current()) = generate-id(preceding-sibling::page[
not(preceding-sibling::node()[1][self::page])
][1])
]

关于xml - XSLT - 分析以下连续节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36273607/

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