1

I'm having problems writing a C# script that'll get me a certain parent element of a given child element. To clear things up, this is an example of the XML tree.

<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>  

Traversing the tree, my script has found the <key> node. What I'm trying to produce is the following tree.

<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>  

As you can see, I'm trying to remove child_element1 and child_element3 in original tree.

I've written a pseudo-code for the script as follows, but so far have failed to figure out how to script the real thing in C#.

  1. Show all the first and second parent elements above of the key node. grandchild_element2 is first parent of key and child_element2 is second parent of key. So all their elements are shown.
  2. Show only node/element that has immediate relation with key for next parent level. parent is third parent of key. The parent element that has direct relation with key is child_element2. So only child_element2 is shown. child_Element1 and child_element2 are not shown because they do not have direct relation with the key

I've taken a look at the following solutions on stackoverflow, but unfortunately they all only show how to get all parent elements (instead of showing the ones which are ancestors of the <key> node.

  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
Community
  • 1
  • 1

1 Answers1

1

This is quite easy if you use an 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>

When the example XML is given a single root element and fed into this XSLT, the result is:

<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>

In case you're unfamiliar with XSLT, an XSLT parameter:

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

is essentially a variable whose value you can pass in from the executing code. Here, I've just given it it the default value C, so it can be run in an XSLT debugger and produce a demonstrable result.

JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • LINQ query will return parents with all other elements – Sergey Berezovskiy Jan 29 '13 at 11:45
  • @lazyberezovsky Yes, it certainly will. That LINQ will obtain a list of the sought value's parent elements, and those will possess all of the children they have in the source XML. But if all the asker wants is a list of the parent elements of the sought value, then that may be sufficient. If the asker's true objective (since it's not 100% clear from the question) is to obtain an XML structure with all of the other stuff omitted, I suggest that s/he use my XSLT solution since it's a lot more efficient and clean than (as far as I know) anything that could be written in C#. – JLRishe Jan 29 '13 at 11:48
  • hi JLRishe and lazyberezovsky, i change the example. maybe it can make 100% clear :) – user2020692 Jan 30 '13 at 04:26