gpt4 book ai didi

xslt - 使用 key : Consolidating multiple
    with intervening

    elements

转载 作者:行者123 更新时间:2023-12-03 16:20:22 25 4
gpt4 key购买 nike

我有多个 xml 实例,类似于以下内容:

<refbody>
<ul>
<li><uicontrol>FOO</uicontrol>BAR</li>
</ul>
<p>Values: 000 - 999</p>
<ul>
<li><uicontrol>FOO</uicontrol>BAR</li>
<li><uicontrol>FOO</uicontrol>BAR</li>
<li><uicontrol>FOO</uicontrol>BAR</li>
<li><uicontrol>FOO</uicontrol>BAR</li>
</ul>
<p>Values:</p>
<p>lorem ipsum</p>
<p>lorem ipsum</p>
<p>lorem ipsum</p>
</refbody>

我希望发生的是合并所有 <ul>元素合并为一个 <dl> .

每个 <li>应该创建一个 child <dlentry> .

每个 <uicontrol>应该变成 <dt>那是它的 <dlentry> 的一个 child .
<li> 中的剩余文本应该放在 <dd>元素,它也是 <dlentry> 的子元素.

我的样式表(在下面提供)已经完成了很多。我遇到麻烦的地方是最后一个要求:

任意 <p>需要放在 <dlentry>里面与其 preceding-sibling::li[1] 相关联.

所以想要的结果是这样的:
<refbody>
<dl>
<dlentry>
<dt>FOO</dt>
<dd>BAR
<p>Values: 000 - 999</p>
</dd>
</dlentry>
<dlentry>
<dt>FOO</dt>
<dd>BAR</dd>
</dlentry>
<dlentry>
<dt>FOO</dt>
<dd>BAR</dd>
</dlentry>
<dlentry>
<dt>FOO</dt>
<dd>BAR</dd>
</dlentry>
<dlentry>
<dt>FOO</dt>
<dd>BAR
<p>Values:</p>
<p>lorem ipsum</p>
<p>lorem ipsum</p>
<p>lorem ipsum</p>
</dd>
</dlentry>
</dl>
</refbody>

我想我需要使用 key 来执行此操作,但我无法让它正常工作。如果有人能告诉我我做错了什么,我将不胜感激。

这是我的样式表:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:key name="kValues" match="p"
use="generate-id[preceding::li[1]]"/>

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

<xsl:template match="ul[ancestor::refbody][1]">
<dl>
<xsl:for-each select="child::li|following::li">
<xsl:variable name="vValues">
<xsl:value-of select="key('kValues',generate-id())"/>
</xsl:variable>
<dlentry>
<dt>
<xsl:value-of select="child::uicontrol"/>
</dt>
<dd>
<xsl:value-of select="text()"/>
<xsl:if test="$vValues">
<xsl:copy-of select="$vValues" />
</xsl:if>
</dd>
</dlentry>
</xsl:for-each>
</dl>
</xsl:template>

</xsl:stylesheet>

最佳答案

一、本次改造 (我使用 key 的解决方案):

<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="kFollowing"
match="node()[self::p or self::text() and preceding-sibling::ul]"
use="generate-id(preceding::li[1])"/>

<xsl:template match="/*[ul]">
<refbody>
<dl>
<xsl:apply-templates/>
</dl>
</refbody>
</xsl:template>

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

<xsl:template match="li/text()">
<dd>
<xsl:value-of select="normalize-space()"/>
</dd>
</xsl:template>

<xsl:template match="li[last()]/text()">
<dd>
<xsl:value-of select="."/>
<xsl:copy-of select="key('kFollowing', generate-id(..))"/>
</dd>
</xsl:template>

<xsl:template match="uicontrol">
<dt>
<xsl:apply-templates/>
</dt>
</xsl:template>
<xsl:template match="p/text()"/>
</xsl:stylesheet>
应用于提供的 XML 文档时 :
<refbody>
<ul>
<li>
<uicontrol>FOO</uicontrol>BAR
</li>
</ul>
<p>Values: 000 - 999</p>
<ul>
<li>
<uicontrol>FOO</uicontrol>BAR
</li>
<li>
<uicontrol>FOO</uicontrol>BAR
</li>
<li>
<uicontrol>FOO</uicontrol>BAR
</li>
<li>
<uicontrol>FOO</uicontrol>BAR
</li>
</ul>
<p>Values:</p>
<p>lorem ipsum</p>
<p>lorem ipsum</p>
<p>lorem ipsum</p>
</refbody>
产生想要的正确结果 :
<refbody>
<dl>
<dlentry>
<dt>FOO</dt>
<dd>BAR
<p>Values: 000 - 999</p>
</dd>
</dlentry>
<dlentry>
<dt>FOO</dt>
<dd>BAR</dd>
</dlentry>
<dlentry>
<dt>FOO</dt>
<dd>BAR</dd>
</dlentry>
<dlentry>
<dt>FOO</dt>
<dd>BAR</dd>
</dlentry>
<dlentry>
<dt>FOO</dt>
<dd>BAR
<p>Values:</p>
<p>lorem ipsum</p>
<p>lorem ipsum</p>
<p>lorem ipsum</p>
</dd>
</dlentry>
</dl>
</refbody>

二、纠正所有发现的错误后的解决方案:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:key name="kValues" match="p"
use="generate-id(preceding::li[1])"/>

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

<xsl:template match="ul[ancestor::refbody][1]">
<dl>
<xsl:for-each select="child::li|following::li">
<xsl:variable name="vValues" select="key('kValues',generate-id())"/>
<dlentry>
<dt>
<xsl:value-of select="child::uicontrol"/>
</dt>
<dd>
<xsl:value-of select="text()[normalize-space()]"/>
<xsl:copy-of select="$vValues" />
</dd>
</dlentry>
</xsl:for-each>
</dl>
</xsl:template>

<xsl:template match="p|ul|text()"/>
</xsl:stylesheet>
当这个更正的转换应用于同一个 XML 文档(上图)时,它会产生所需的正确结果 .

三、我发现的错误分析 :
  • 这是一个需要睁大眼睛才能看到的错误:

  • ...
    <xsl:key name="kValues" match="p"             
    use="generate-id[preceding::li[1]]"/>
    ...
    这里有 p元素由其 generate-id 的字符串值索引具有前面 li 的子级.
    但是,没有名为 generate-id 的元素。在 XML 文档中。
    真正的意图是使用 generate-id()功能 .函数调用由函数名组成,后跟一系列实际参数值,用常规圆括号 ( 括起来。和 ) .用方括号替换圆括号从根本上改变了表达式的语义,将函数调用变成了(相对)定位步骤。
    .2. 这个 :
            <xsl:variable name="vValues">                               
    <xsl:value-of select="key('kValues',generate-id())"/>
    </xsl:variable>
    不仅是(非常)不好的做法,而且经常导致错误 ,就像在当前情况下一样。您正在创建树(文档节点),而不是元素的节点集。树总是至少有一个节点(文档节点)和它的 bool 值,因此总是正确的。
    永远不要使用上述语法。
    正确的变量声明是 :
                <xsl:variable name="vValues" select="key('kValues',generate-id())"/>
    .3.没有模板规则可以防止身份模板复制任何不需要的 ul , p , 和 text()节点和这些出现在原始转换的结果中。

    关于xslt - 使用 key : Consolidating multiple <ul> with intervening <p> elements,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11656386/

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