Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 如何使用xsl:key获得元素的唯一结构_Xml_Xslt_Xslt 2.0 - Fatal编程技术网

Xml 如何使用xsl:key获得元素的唯一结构

Xml 如何使用xsl:key获得元素的唯一结构,xml,xslt,xslt-2.0,Xml,Xslt,Xslt 2.0,请给出建议,如何使用xsl:key避免重复元素列表(我从variable方法获得结果,但这不是一种有效的方法)。请建议 在我的输入中,“Ref”是主元素,它有几个子元素。只需列出其结构(仅元素名称,而非内容)唯一的“Ref”元素。如果为13和10012001,则只应显示第一个。在给定的输入中,忽略'au'和'ed'元素作为它们的祖先 输入XML: <article> <Ref id="ref1"> <RefText> <autho

请给出建议,如何使用xsl:key避免重复元素列表(我从variable方法获得结果,但这不是一种有效的方法)。请建议

在我的输入中,“Ref”是主元素,它有几个子元素。只需列出其结构(仅元素名称,而非内容)唯一的“Ref”元素。如果为13和10012001,则只应显示第一个。在给定的输入中,忽略'au'和'ed'元素作为它们的祖先

输入XML:

<article>
<Ref id="ref1">
    <RefText>
        <authors><au><snm>Kishan</snm><fnm>TR</fnm></au><au><snm>Rudramuni</snm><fnm>TP</fnm></au></authors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2016</Year><vol>1</vol>
        <fpage>12</fpage><lpage>14</lpage>
    </RefText></Ref><!-- should list -->

<Ref id="ref2">
    <RefText>
        <authors><au><snm>Rudramuni</snm><fnm>TP</fnm></au></authors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><vol>2</vol>
        <fpage>22</fpage><lpage>24</lpage>
        </RefText></Ref><!-- This Ref should not list in output xml, because 'authors, articleTitle, like other same type elements present, ref2 is same as ref1. -->

<Ref id="ref3">
    <RefText>
        <authors><au><snm>Likhith</snm><fnm>MD</fnm></au></authors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><fpage>22</fpage><lpage>24</lpage>
        </RefText></Ref><!-- It should list, bcs, 'vol' missing here, then it is unique in structure with respect to prev Refs -->

<Ref id="ref4">
    <RefText>
        <authors><au><snm>Kowshik</snm><fnm>MD</fnm></au></authors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><fpage>22</fpage>
        </RefText></Ref><!-- should list, bcs, 'lpage' missing -->

<Ref id="ref5">
    <RefText>
        <editors><au><snm>Dhyan</snm><fnm>MD</fnm></au></editors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><fpage>22</fpage>
        </RefText></Ref><!-- should list, bcs, 'editors' missing -->

<Ref id="ref6">
    <RefText>
        <editors><ed><snm>Kishan</snm><fnm>TR</fnm></ed></editors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year>
        </RefText></Ref><!-- should list -->

<Ref id="ref7">
    <RefText>
        <editors><ed><snm>Vivan</snm><fnm>S</fnm></ed></editors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year>
        </RefText></Ref><!-- should not, same type elements in ref6 and ref7 -->

<Ref id="ref8">
    <RefText><editors><au><snm>Dhyan</snm><fnm>MD</fnm></au><au><snm>Dhyan</snm><fnm>MD</fnm></au></editors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><fpage>22</fpage>
        </RefText></Ref><!-- should not, bcs, 'Ref5 and Ref8' are having same elements -->

</article>
<article>
<Ref id="ref1">
    <RefText>
        <authors><au><snm>Kishan</snm><fnm>TR</fnm></au><au><snm>Rudramuni</snm><fnm>TP</fnm></au></authors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2016</Year><vol>1</vol>
        <fpage>12</fpage><lpage>14</lpage>
    </RefText></Ref>
<Ref id="ref3">
    <RefText>
        <authors><au><snm>Likhith</snm><fnm>MD</fnm></au></authors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><fpage>22</fpage><lpage>24</lpage>
        </RefText></Ref>
<Ref id="ref4">
    <RefText>
        <authors><au><snm>Kowshik</snm><fnm>MD</fnm></au></authors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><fpage>22</fpage>
        </RefText></Ref>
<Ref id="ref5">
    <RefText><editors><au><snm>Dhyan</snm><fnm>MD</fnm></au></editors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><fpage>22</fpage>
        </RefText></Ref>
<Ref id="ref6">
    <RefText>
        <editors><ed><snm>Kishan</snm><fnm>TR</fnm></ed></editors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year>
        </RefText></Ref>
</article>

Kishantrudramunitp
文章标题
20161
1214
RudramuniTP
文章标题
20172
2224
LikhithMD
文章标题
20172224
九龙
文章标题
201722
迪扬姆德
文章标题
201722
基尚
文章标题
2017
万岁
文章标题
2017
DhyanMDDhyanMD
文章标题
201722
XSLT2.0: 在这里,我考虑了存储前面Ref的子代名称的变量

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

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

<xsl:template match="article">
    <article>

        <xsl:for-each select="descendant::Ref">
            <xsl:variable name="varPrev">
            <xsl:for-each select="preceding::Ref">
                <a>
                    <xsl:text>|</xsl:text>
                        <xsl:for-each select="descendant::*[not(ancestor-or-self::au) and not(ancestor-or-self::ed)]">
                            <xsl:value-of select="name()"/>
                        </xsl:for-each>
                    <xsl:text>|</xsl:text>
                </a>
            </xsl:for-each>
        </xsl:variable>
            <xsl:variable name="varPresent">
                <a>
                    <xsl:text>|</xsl:text>
                        <xsl:for-each select="descendant::*[not(ancestor-or-self::au) and not(ancestor-or-self::ed)]">
                            <xsl:value-of select="name()"/>
                        </xsl:for-each>
                    <xsl:text>|</xsl:text>
                </a>
            </xsl:variable>
            <xsl:if test="not(contains($varPrev, $varPresent))">
                <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
            </xsl:if>

        </xsl:for-each>
    </article>
</xsl:template>

<!--xsl:key name="keyRef" match="Ref" use="descendant::*"/>

<xsl:template match="article">
    <xsl:for-each select="descendant::Ref">
        <xsl:if test="count('keyRef', ./name())=1">
            <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
        </xsl:if>
    </xsl:for-each>
</xsl:template-->

</xsl:stylesheet>

|
|
|
|
所需结果:

<article>
<Ref id="ref1">
    <RefText>
        <authors><au><snm>Kishan</snm><fnm>TR</fnm></au><au><snm>Rudramuni</snm><fnm>TP</fnm></au></authors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2016</Year><vol>1</vol>
        <fpage>12</fpage><lpage>14</lpage>
    </RefText></Ref><!-- should list -->

<Ref id="ref2">
    <RefText>
        <authors><au><snm>Rudramuni</snm><fnm>TP</fnm></au></authors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><vol>2</vol>
        <fpage>22</fpage><lpage>24</lpage>
        </RefText></Ref><!-- This Ref should not list in output xml, because 'authors, articleTitle, like other same type elements present, ref2 is same as ref1. -->

<Ref id="ref3">
    <RefText>
        <authors><au><snm>Likhith</snm><fnm>MD</fnm></au></authors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><fpage>22</fpage><lpage>24</lpage>
        </RefText></Ref><!-- It should list, bcs, 'vol' missing here, then it is unique in structure with respect to prev Refs -->

<Ref id="ref4">
    <RefText>
        <authors><au><snm>Kowshik</snm><fnm>MD</fnm></au></authors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><fpage>22</fpage>
        </RefText></Ref><!-- should list, bcs, 'lpage' missing -->

<Ref id="ref5">
    <RefText>
        <editors><au><snm>Dhyan</snm><fnm>MD</fnm></au></editors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><fpage>22</fpage>
        </RefText></Ref><!-- should list, bcs, 'editors' missing -->

<Ref id="ref6">
    <RefText>
        <editors><ed><snm>Kishan</snm><fnm>TR</fnm></ed></editors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year>
        </RefText></Ref><!-- should list -->

<Ref id="ref7">
    <RefText>
        <editors><ed><snm>Vivan</snm><fnm>S</fnm></ed></editors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year>
        </RefText></Ref><!-- should not, same type elements in ref6 and ref7 -->

<Ref id="ref8">
    <RefText><editors><au><snm>Dhyan</snm><fnm>MD</fnm></au><au><snm>Dhyan</snm><fnm>MD</fnm></au></editors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><fpage>22</fpage>
        </RefText></Ref><!-- should not, bcs, 'Ref5 and Ref8' are having same elements -->

</article>
<article>
<Ref id="ref1">
    <RefText>
        <authors><au><snm>Kishan</snm><fnm>TR</fnm></au><au><snm>Rudramuni</snm><fnm>TP</fnm></au></authors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2016</Year><vol>1</vol>
        <fpage>12</fpage><lpage>14</lpage>
    </RefText></Ref>
<Ref id="ref3">
    <RefText>
        <authors><au><snm>Likhith</snm><fnm>MD</fnm></au></authors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><fpage>22</fpage><lpage>24</lpage>
        </RefText></Ref>
<Ref id="ref4">
    <RefText>
        <authors><au><snm>Kowshik</snm><fnm>MD</fnm></au></authors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><fpage>22</fpage>
        </RefText></Ref>
<Ref id="ref5">
    <RefText><editors><au><snm>Dhyan</snm><fnm>MD</fnm></au></editors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year><fpage>22</fpage>
        </RefText></Ref>
<Ref id="ref6">
    <RefText>
        <editors><ed><snm>Kishan</snm><fnm>TR</fnm></ed></editors>
        <artTitle>The article1</artTitle><jTitle>Journal title</jTitle>
        <Year>2017</Year>
        </RefText></Ref>
</article>

Kishantrudramunitp
文章标题
20161
1214
LikhithMD
文章标题
20172224
九龙
文章标题
201722
迪扬姆德
文章标题
201722
基尚
文章标题
2017

这里尝试使用与字符串比较类似的计算键:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf" exclude-result-prefixes="mf xs">

    <xsl:function name="mf:fingerprint" as="xs:string">
        <xsl:param name="input-element" as="element()"/>
        <xsl:value-of select="for $d in $input-element/descendant::*[not(ancestor-or-self::au) and not(ancestor-or-self::ed)] return node-name($d)" separator="|"/>
    </xsl:function>

    <xsl:key name="group" match="Ref" use="mf:fingerprint(.)"/>

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

    <xsl:template match="Ref[not(. is key('group', mf:fingerprint(.))[1])]"/>
</xsl:transform>


就我所知,它似乎可以完成这项工作,但我不太确定名称的字符串串联是否足以处理所有类型的输入。

这里尝试使用与字符串比较类似的计算键:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf" exclude-result-prefixes="mf xs">

    <xsl:function name="mf:fingerprint" as="xs:string">
        <xsl:param name="input-element" as="element()"/>
        <xsl:value-of select="for $d in $input-element/descendant::*[not(ancestor-or-self::au) and not(ancestor-or-self::ed)] return node-name($d)" separator="|"/>
    </xsl:function>

    <xsl:key name="group" match="Ref" use="mf:fingerprint(.)"/>

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

    <xsl:template match="Ref[not(. is key('group', mf:fingerprint(.))[1])]"/>
</xsl:transform>


就我所知,它似乎可以完成这项工作,但我不太确定名称的字符串串联是否足以处理所有类型的输入。

我建议以下方法:

  • 删除
    作者
    编辑器
    的后代以及所有文本节点

  • 使用
    deep-equal()
    比较其余节点

下面是一个简化的概念证明:

XSLT2.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:strip-space elements="*"/>

<xsl:template match="/article">
    <xsl:variable name="first-pass">
        <xsl:apply-templates mode="first-pass"/>
    </xsl:variable>
    <xsl:copy>
        <xsl:for-each select="$first-pass/Ref[not(some $ref in preceding-sibling::Ref satisfies deep-equal(RefText, $ref/RefText))]">
            <Ref id="{@id}"/>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

<!-- identity transform -->
<xsl:template match="@*|node()" mode="#all">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" mode="#current"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="authors | editors" mode="first-pass">
    <xsl:copy/>
</xsl:template>

<xsl:template match="text()" mode="first-pass" priority="0"/>

</xsl:stylesheet>

结果

<?xml version="1.0" encoding="UTF-8"?>
<article>
   <Ref id="ref1"/>
   <Ref id="ref3"/>
   <Ref id="ref4"/>
   <Ref id="ref5"/>
   <Ref id="ref6"/>
</article>

我建议采用以下方法:

  • 删除
    作者
    编辑器
    的后代以及所有文本节点

  • 使用
    deep-equal()
    比较其余节点

下面是一个简化的概念证明:

XSLT2.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:strip-space elements="*"/>

<xsl:template match="/article">
    <xsl:variable name="first-pass">
        <xsl:apply-templates mode="first-pass"/>
    </xsl:variable>
    <xsl:copy>
        <xsl:for-each select="$first-pass/Ref[not(some $ref in preceding-sibling::Ref satisfies deep-equal(RefText, $ref/RefText))]">
            <Ref id="{@id}"/>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

<!-- identity transform -->
<xsl:template match="@*|node()" mode="#all">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" mode="#current"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="authors | editors" mode="first-pass">
    <xsl:copy/>
</xsl:template>

<xsl:template match="text()" mode="first-pass" priority="0"/>

</xsl:stylesheet>

结果

<?xml version="1.0" encoding="UTF-8"?>
<article>
   <Ref id="ref1"/>
   <Ref id="ref3"/>
   <Ref id="ref4"/>
   <Ref id="ref5"/>
   <Ref id="ref6"/>
</article>


您所说的“忽略'au'和'ed'元素作为它们的祖先”到底是什么意思?你想考虑整个结构吗?如果没有,排除其中某些部分的确切逻辑是什么此外,每个
Ref
1中的元素顺序是否相同。只考虑作者的名字,如果两个,三个,更多的S也只是一个主要的“作者”组。因为引用可能有不同的作者编号,但“vol”“page”其他元素可能相同。2.顺序不同也是唯一的,即“a,b”与“b,a”是唯一的。(顺序不同,则需要视为唯一)。我不明白#1。我怀疑如果您删除文本值(+您不想考虑的元素)并对结果节点进行
deep-equal()
比较,您可能会得到预期的结果。先生,在我的输入xml中,Ref 1和Ref2是相同的,即使第一个Ref的“authors”元素有两个“au”,但是第二个“Ref”的“authors”元素只有一个“au”。如果“作者”和“编辑”,那么内部元素就不需要考虑了。(参考文献2是重复的)那么只比较
RefText
的直接子元素并忽略它们的后代就足够了吗?你所说的“忽略'au'和'ed'元素作为它们的祖先”到底是什么意思?你想考虑整个结构吗?如果没有,排除其中某些部分的确切逻辑是什么此外,每个
Ref
1中的元素顺序是否相同。只考虑作者的名字,如果两个,三个,更多的S也只是一个主要的“作者”组。因为引用可能有不同的作者编号,但“vol”“page”其他元素可能相同。2.顺序不同也是唯一的,即“a,b”与“b,a”是唯一的。(顺序不同,则需要视为唯一)。我不明白#1。我怀疑如果您删除文本值(+您不想考虑的元素)并对结果节点进行
deep-equal()
比较,您可能会得到预期的结果