如何在发现子条件时获取某些父元素节点

时间:2013-01-29 10:29:19

标签: c# xml xelement

我在编写C#脚本时遇到问题,该脚本会让我获得给定子元素的某个父元素。为了清楚起见,这是XML树的一个例​​子。

<parent attribute='X'>
  <child_element1>A</child_element1>
  <child_element2 attribute='Y'>
    <grandchild_element1>B</grandchild_element1>
    <grandchild_element2>
      <key>C</key>
    </grandchild_element2>
    <grandchild_element3>D</grandchild_element3>
  </child_element2>
  <child_element3>E</child_element3>
</parent>  

遍历树,我的脚本找到了<key>节点。我想要制作的是以下树。

<parent attribute='X'>
  <child_element2 attribute='Y'>
    <grandchild_element1>B</grandchild_element1>
    <grandchild_element2>
      <key>C</key>
    </grandchild_element2>
    <grandchild_element3>D</grandchild_element3>
  </child_element2>
</parent>  

如您所见,我正在尝试删除原始树中的child_element1child_element3

我为脚本编写了一个伪代码,如下所示,但到目前为止还没有弄清楚如何编写C#中的真实脚本。

  1. 显示关键节点上方的所有第一个和第二个父元素。 grandchild_element2是密钥的第一个父级,child_element2是密钥的第二个父级。所以他们所有的元素都显示出来了。
  2. 仅显示与下一个父级别的密钥有直接关系的节点/元素。 parent是密钥的第三个父级。与密钥直接关联的parent元素为child_element2。因此只显示child_element2child_Element1child_element2未显示,因为它们与密钥没有直接关系
  3. 我已经在stackoverflow上看了下面的解决方案,但不幸的是它们都只展示了如何获取所有父元素(而不是显示那些是<key>节点的祖先。

    1. Retrieve XML parent node attribute if child node meets a certain criteria and assign both to variables
    2. C# XML, find node and all his parents

1 个答案:

答案 0 :(得分:1)

如果您使用XSLT,这很容易:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>
  <xsl:param name="valueToFind" select="'C'" omit-xml-declaration="yes" />

  <xsl:template match="/*">
    <xsl:apply-templates select="node()[descendant-or-self::node() = $valueToFind]" />
  </xsl:template>

  <xsl:template match="*">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates 
            select="node()[descendant-or-self::node() = $valueToFind]" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

当为示例XML提供单个根元素并将其提供给此XSLT时,结果为:

<a>
  <a.1 name="First">
    <a.1.2>
      <a.1.2.2>
        <key>C</key>
      </a.1.2.2>
    </a.1.2>
  </a.1>
</a>

如果您不熟悉XSLT,则需要使用XSLT参数:

<xsl:param name="valueToFind" select="'C'" />

本质上是一个变量,其值可以从执行代码中传入。在这里,我刚给它默认值C,因此它可以在XSLT调试器中运行并产生可证明的结果。