首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XPath -从非重复列表中获取具有不同文本值的节点

XPath -从非重复列表中获取具有不同文本值的节点
EN

Stack Overflow用户
提问于 2015-09-01 20:55:31
回答 3查看 2K关注 0票数 1

我有一个XML如下所示:

代码语言:javascript
复制
<object>
    <codes>
        <cd1>A</cd1>
        <cd2>B</cd2>
        <cd3>C</cd3>
    </codes>
    <codes>
        <cd1>A</cd1>
        <cd2>D</cd2>
        <cd3></cd3>
    </codes>
    <codes>
        <cd1>E</cd1>
        <cd2>D</cd2>
        <cd3></cd3>
    </codes>
</object>

到目前为止,我的XPath发展过程如下:

  1. //cd1|//cd2|//cd3:获取所有cd1、cd2和cd3元素
  2. (//cd1|//cd2|//cd3)[text()[1]]:从上面的列表中过滤所有具有非空文本值的元素,并返回以下元素。 <cd1>A</cd1> <cd2>B</cd2> <cd3>C</cd3> <cd1>A</cd1> <cd2>D</cd2> <cd1>E</cd1> <cd2>D</cd2>
  3. 现在,我需要删除具有重复文本值的元素。我尝试过xpath作为(//cd1|//cd2|//cd3)[text()[1]][(preceding::cd1)|(preceding::cd2)|(preceding::cd3)]。我希望实现的是检查该值是否在上面的cd1、cd2或cd3中的前面。但是,在<cd2>D</cd2>重复的情况下,这会返回到下面。 <cd2>B</cd2> <cd3>C</cd3> <cd1>A</cd1> <cd2>D</cd2> <cd1>E</cd1> <cd2>D</cd2>

如何编写xpath来解决上述(3)问题?

请注意,我必须使用XPath1.0,因此distinct value函数不是一个选项。另外,我需要获得匹配的节点列表,而不是xpath中的文本值,因为我必须使用AXIOM对这些节点进行更多的处理。

Update :我正在使用这个xpath获取匹配的元素,然后使用AXIOM进行处理。因此,我需要编写一个xpath表达式来一次获得匹配的元素(我不能用AXIOM或使用XSLT编写自定义流)。另外,cd*不能使用,因为实名不匹配。我在这里用了一个样品。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-09-01 23:01:03

试试这个:

代码语言:javascript
复制
//cd1[not(text() = preceding::cd1/text())][normalize-space()]|
//cd2[not(text() = preceding::cd2/text())][normalize-space()]|
//cd3[not(text() = preceding::cd3/text())][normalize-space()]
票数 1
EN

Stack Overflow用户

发布于 2015-09-01 21:37:46

我发现的一种方法是使用以下模板:

代码语言:javascript
复制
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
    <xsl:for-each select="//*[starts-with(node-name(.), 'cd')]">
        <xsl:variable name="content"><xsl:value-of select="text()"/></xsl:variable>
        <xsl:if test="count(preceding::*[starts-with(node-name(.), 'cd') and text() = $content]) = 0 and text()">
               <xsl:copy-of select="."/> 
            </xsl:if>
     </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

这将获取所有cd*元素,并获取每个cd*元素的内容,用于计算具有相同内容的前面有多少个--如果为0,则使用它。

据我所知,这是在xslt-1中(使用变量)的唯一方法。这是因为您不能返回xpath中的引用,除非变量中有值(并且需要将"current“(外部)文本与"current”(xpath中的节点)文本进行比较)。

希望这能有所帮助。

票数 1
EN

Stack Overflow用户

发布于 2015-09-01 22:20:22

这实际上是非常简单的Muenchian分组,只有三个键:

代码语言:javascript
复制
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="xml" />
<xsl:key name="cd1" match="//cd1" use="text()" />
<xsl:key name="cd2" match="//cd2" use="text()" />
<xsl:key name="cd3" match="//cd3" use="text()" />

<xsl:template match="/">    
    <xsl:for-each select="/object/codes/cd1[./text() != '' and count(. | key('cd1', .)[1]) = 1]">
        <xsl:copy-of select="." />
    </xsl:for-each>

    <xsl:for-each select="/object/codes/cd2[./text() != '' and count(. | key('cd2', .)[1]) = 1]">
        <xsl:copy-of select="." />
    </xsl:for-each>
    <xsl:for-each select="/object/codes/cd3[./text() != '' and count(. | key('cd3', .)[1]) = 1]">
        <xsl:copy-of select="." />
    </xsl:for-each>

</xsl:template>
</xsl:stylesheet>

输出:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<cd1>A</cd1>
<cd1>E</cd1>
<cd2>B</cd2>
<cd2>D</cd2>
<cd3>C</cd3>

或者,如果您想对它们进行分组,而不管节点名称(即,如果cd1cd2都将A作为文本值),那么就不那么简单了。

代码语言:javascript
复制
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="xml" />
<xsl:key name="cd" match="//cd1 | //cd2 | //cd3" use="text()" />

<xsl:template match="/">    
    <xsl:for-each select="/object/codes/cd1[./text() != '' and count(. | key('cd', .)[1]) = 1] | /object/codes/cd2[./text() != '' and count(. | key('cd', .)[1]) = 1] | /object/codes/cd3[./text() != '' and count(. | key('cd', .)[1]) = 1]">
        <xsl:copy-of select="." />
    </xsl:for-each>


</xsl:template>
</xsl:stylesheet>

这将提供与上面相同的输出(但按当前模板输出的方式排序),但将消除共享相同文本的cd1cd2cd3之间的重复(只使用第一个文本)。

还请注意,我忽略了可能不需要的空节点(并且可以通过从选择器中删除./text() != ''轻松地修复),但是,如果需要的话,必须使用不同的方法来消除重复的空节点(可能只是一系列测试空节点的模板或xsl:if,如果在这种情况下存在,则输出一个单独的模板)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32340762

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档