xpath: 所有具有异常的节点?

huangapple go评论61阅读模式
英文:

xpath: All nodes with exceptions?

问题

这是我的第一次尝试使用xpath,但我失败了。

考虑这样的情况:

<node1>
  <node11>
    <dependent>Retain</dependent>
    <dependent polarity="positive">Retain</dependent>
    <dependent polarity="negative">Discard</dependent>
  </node11>
  <dependent>Retain</dependent>
  <dependent polarity="positive">Retain</dependent>
  <dependent polarity="negative">Discard</dependent>
  <somethingelse>Retain</somethingelse>
</node1>

我正在寻找一个表达式,该表达式将(保持树结构的同时):

  1. 返回所有不命名为dependent的节点,
  2. 返回没有名为polarity的属性的名为dependent的节点,
  3. 返回名为dependent且具有属性polarity设置为positive的节点。

上面的示例将如下结果:

<node1>
  <node11>
    <dependent>Retain</dependent>
    <dependent polarity="positive">Retain</dependent>
  </node11>
  <dependent>Retain</dependent>
  <dependent polarity="positive">Retain</dependent>
  <somethingelse>Retain</somethingelse>
</node1>

许多尝试使用Google和ChatGPT都没有产生我想要的结果。以下是我认为应该有效但实际上不起作用的内容 - polarity='negative'节点被保留了!?

//*[not(self::dependent) or (descendant-or-self::dependent[not(@polarity)]) or (descendant-or-self::dependent[@polarity='positive'])]

我在哪里出错了?

英文:

This is my first foray into xpath and I'm failing miserably.

Consider something like this:

<node1>
  <node11>
    <dependent>Retain</dependent>
    <dependent polarity="positive">Retain</dependent>
    <dependent polarity="negative">Discard</dependent>
  </node11>
  <dependent>Retain</dependent>
  <dependent polarity="positive">Retain</dependent>
  <dependent polarity="negative">Discard</dependent>
  <somethingelse>Retain</somethingelse>
</node1>

I'm looking for an expression that will (while maintaining tree structure)

  1. return all nodes not named dependent,
  2. return nodes named dependent that do not have an attribute named polarity
  3. return nodes named dependent with attribute polarityset to positive.

Above example would thus result in:

<node1>
  <node11>
    <dependent>Retain</dependent>
    <dependent polarity="positive">Retain</dependent>
  </node11>
  <dependent>Retain</dependent>
  <dependent polarity="positive">Retain</dependent>
  <somethingelse>Retain</somethingelse>
</node1>

Many attempts at googleing and ChatGPLing have not produced what I want. Below is what I believe should work, but doesn't - polarity='negative' nodes are retained!?

//*[not(self::dependent) or (descendant-or-self::dependent[not(@polarity)]) or (descendant-or-self::dependent[@polarity='positive'])]

Where do I err?

答案1

得分: 3

您可以使用类似以下的内容:

//*[not(self::dependent[@polarity!='positive'])]

但由于您选择了每个元素,它将选择根元素(node1),这将包括所有内容。如果您尝试修改树结构,您可能需要使用 xquery 或 xslt。

以下是生成所需输出的 XSLT 示例:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:mode on-no-match="shallow-copy"/>
    
    <xsl:template match="dependent[@polarity!='positive']"/>
    
</xsl:stylesheet>

XSLT 1.0 版本(将 xsl:mode 替换为标识模板):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="dependent[@polarity!='positive']"/>
    
</xsl:stylesheet>
英文:

You could use something like this:

//*[not(self::dependent[@polarity!=&#39;positive&#39;])]

But since you're selecting each element, it's going to select the root element (node1) and that's going to include everything anyway. If you're trying to modify the tree, you'll probably want to use xquery or xslt.

Example of XSLT that results in the desired output:

&lt;xsl:stylesheet version=&quot;3.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
    &lt;xsl:output indent=&quot;yes&quot;/&gt;
    &lt;xsl:strip-space elements=&quot;*&quot;/&gt;
    
    &lt;xsl:mode on-no-match=&quot;shallow-copy&quot;/&gt;
    
    &lt;xsl:template match=&quot;dependent[@polarity!=&#39;positive&#39;]&quot;/&gt;
    
&lt;/xsl:stylesheet&gt;

XSLT 1.0 version (replaced xsl:mode with identity template)...

&lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
    &lt;xsl:output indent=&quot;yes&quot;/&gt;
    &lt;xsl:strip-space elements=&quot;*&quot;/&gt;
    
    &lt;xsl:template match=&quot;@*|node()&quot;&gt;
        &lt;xsl:copy&gt;
            &lt;xsl:apply-templates select=&quot;@*|node()&quot;/&gt;
        &lt;/xsl:copy&gt;
    &lt;/xsl:template&gt;
    
    &lt;xsl:template match=&quot;dependent[@polarity!=&#39;positive&#39;]&quot;/&gt;
    
&lt;/xsl:stylesheet&gt;

答案2

得分: 3

XPath 旨在从输入中选择一组节点;它无法用于创建一个包含一些原始节点但不包含其他节点的修改后的树结构。为此,您需要使用 XSLT 或 XQuery。

在 XSLT 3.0 中,您可以通过一组模板规则来实现您的任务,类似于以下内容:

<xsl:mode on-no-match="shallow-copy"/>

<xsl:template match="dependent[@polarity!='positive']"/>

xsl:mode 声明表示默认情况下您希望复制元素节点并对其子节点应用模板;xsl:template 规则表示,如果您找到一个名为 dependent 的元素,其 polarity 值不是 positive,则您不希望产生与该节点相关的任何输出。

英文:

XPath is designed to select a set of nodes from your input; it can't be used to create a modified tree structure containing some of the original nodes and not others. For that you need XSLT or XQuery.

In XSLT 3.0 you would achieve your task with a set of template rules something like this:

&lt;xsl:mode on-no-match=&quot;shallow-copy&quot;/&gt;

&lt;xsl:template match=&quot;dependent[@polarity!=&#39;positive&#39;]&quot;/&gt;

The xsl:mode declaration says that by default you want to copy element nodes and apply-templates to their children; the xsl:template rule says that if you find an element named dependent with a polarity value other than positive then you want to produce no output in respect of that node.

huangapple
  • 本文由 发表于 2023年7月3日 23:04:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76605970.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定