473,287 Members | 1,629 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,287 software developers and data experts.

Remove a nodes where attribute has specified text. (Variable depth xml)

I have an XML document as follows:

<Menu>
<Group>
<Item Text="About Us" AccessRoles="All">
<Group>
<Item Text="Option 1" AccessRoles="All" />
<Item Text="Option 2" AccessRoles="All" />
<Item Text="Option 3" AccessRoles="All" />
</Group>
</Item>
<Item Text="Projects" AccessRoles="All">
<Group>
<Item Text="Option 1" AccessRoles="All" />
<Item Text="Option 2" AccessRoles="Employee" />
<Item Text="Option 3" AccessRoles="Manager,Executive" />
</Group>
</Item>
<Item Text="Library" AccessRoles="Employee,Manager,Executive">
<Group>
<Item Text="Option 1" AccessRoles="Employee" />
<Item Text="Option 2" AccessRoles="Manager" />
<Item Text="Option 3" AccessRoles="Executive" />
</Group>
</Item>
</Group>
</Menu>

This xml is used for telerik RADMenu component and before I use it with
the control I want to read the document and remove any menu options
(<Item>) that the current logged in user does not have roles for.

At the point of reading/parsing the document I have a comma-delimited
string (or ArrayList) of roles assigned to the current user (including
role "All") and so I need to check to see if any of the roles exist in
the AccessRoles attribute for each item.

The problem I am having is in removing the nodes that do not meet the
criteria.

I have been going down the following route (please note that this code
is only checking for the "All" role)...

Public Shared Function GetRoleBasedMenuXml() As String
Dim strMenuXml As String
Dim xmldocMenu As XmlDocument
strMenuXml = HttpContext.Current.Cache.Get("PortMenuXML")

xmldocMenu = New XmlDocument
xmldocMenu.LoadXml(strMenuXml)
Dim xmlnlMenuItem As XmlNodeList =
xmldocMenu.GetElementsByTagName("Item")

For Each xmlNode As XmlNode In xmlnlMenuItem
If Not xmlNode.Attributes("AccessRoles") Is Nothing Then
If xmlNode.Attributes("AccessRoles").Value <> "All" Then
xmlNode.RemoveAll()
xmlNode.RemoveChild(xmlNode.Parent)
End If
End If
Next

Dim swFormattedMenuXML As StringWriter
swFormattedMenuXML = New StringWriter
xmldocMenu.Save(swFormattedMenuXML)
Return swFormattedMenuXML.ToString()
End Function

The problem with this is that the RemoveAll() method only removes the
child nodes and the current node attributes leaving <Item></Item>. I
have tried to use xmlNode.ParentNode.RemoveChild(xmlNode) after the
RemoveAll but this is invalid in a For Each loop! I have spent most of
my day trying to find different ways around this problem (XPath etc.)
but because it is variable depth and also the nature of the AccessRoles
validation it has proved unfruitful - I am missing something!

Any help/suggestions would be greatly appreciated!

Nov 12 '05 #1
8 2614
This is a task that can be accomplished nicely with XSLT. Just override the
identity rule with an empty rule that matches the nodes to be removed.
Cheers,
Dimitre Novatchev.
"Mikey" <mi*****@sivers.co.uk> wrote in message
news:11**********************@g49g2000cwa.googlegr oups.com...
I have an XML document as follows:

<Menu>
<Group>
<Item Text="About Us" AccessRoles="All">
<Group>
<Item Text="Option 1" AccessRoles="All" />
<Item Text="Option 2" AccessRoles="All" />
<Item Text="Option 3" AccessRoles="All" />
</Group>
</Item>
<Item Text="Projects" AccessRoles="All">
<Group>
<Item Text="Option 1" AccessRoles="All" />
<Item Text="Option 2" AccessRoles="Employee" />
<Item Text="Option 3" AccessRoles="Manager,Executive" />
</Group>
</Item>
<Item Text="Library" AccessRoles="Employee,Manager,Executive">
<Group>
<Item Text="Option 1" AccessRoles="Employee" />
<Item Text="Option 2" AccessRoles="Manager" />
<Item Text="Option 3" AccessRoles="Executive" />
</Group>
</Item>
</Group>
</Menu>

This xml is used for telerik RADMenu component and before I use it with
the control I want to read the document and remove any menu options
(<Item>) that the current logged in user does not have roles for.

At the point of reading/parsing the document I have a comma-delimited
string (or ArrayList) of roles assigned to the current user (including
role "All") and so I need to check to see if any of the roles exist in
the AccessRoles attribute for each item.

The problem I am having is in removing the nodes that do not meet the
criteria.

I have been going down the following route (please note that this code
is only checking for the "All" role)...

Public Shared Function GetRoleBasedMenuXml() As String
Dim strMenuXml As String
Dim xmldocMenu As XmlDocument
strMenuXml = HttpContext.Current.Cache.Get("PortMenuXML")

xmldocMenu = New XmlDocument
xmldocMenu.LoadXml(strMenuXml)
Dim xmlnlMenuItem As XmlNodeList =
xmldocMenu.GetElementsByTagName("Item")

For Each xmlNode As XmlNode In xmlnlMenuItem
If Not xmlNode.Attributes("AccessRoles") Is Nothing Then
If xmlNode.Attributes("AccessRoles").Value <> "All" Then
xmlNode.RemoveAll()
xmlNode.RemoveChild(xmlNode.Parent)
End If
End If
Next

Dim swFormattedMenuXML As StringWriter
swFormattedMenuXML = New StringWriter
xmldocMenu.Save(swFormattedMenuXML)
Return swFormattedMenuXML.ToString()
End Function

The problem with this is that the RemoveAll() method only removes the
child nodes and the current node attributes leaving <Item></Item>. I
have tried to use xmlNode.ParentNode.RemoveChild(xmlNode) after the
RemoveAll but this is invalid in a For Each loop! I have spent most of
my day trying to find different ways around this problem (XPath etc.)
but because it is variable depth and also the nature of the AccessRoles
validation it has proved unfruitful - I am missing something!

Any help/suggestions would be greatly appreciated!

Nov 12 '05 #2
Reverse this call:
xmlNode.RemoveChild(xmlNode.Parent)

To become:
xmlNode.Parent.RemoveChild(xmlNode);

Then you don't even need:
xmlNode.RemoveAll()
"Mikey" <mi*****@sivers.co.uk> wrote in message
news:11**********************@g49g2000cwa.googlegr oups.com...
I have an XML document as follows:

<Menu>
<Group>
<Item Text="About Us" AccessRoles="All">
<Group>
<Item Text="Option 1" AccessRoles="All" />
<Item Text="Option 2" AccessRoles="All" />
<Item Text="Option 3" AccessRoles="All" />
</Group>
</Item>
<Item Text="Projects" AccessRoles="All">
<Group>
<Item Text="Option 1" AccessRoles="All" />
<Item Text="Option 2" AccessRoles="Employee" />
<Item Text="Option 3" AccessRoles="Manager,Executive" />
</Group>
</Item>
<Item Text="Library" AccessRoles="Employee,Manager,Executive">
<Group>
<Item Text="Option 1" AccessRoles="Employee" />
<Item Text="Option 2" AccessRoles="Manager" />
<Item Text="Option 3" AccessRoles="Executive" />
</Group>
</Item>
</Group>
</Menu>

This xml is used for telerik RADMenu component and before I use it with
the control I want to read the document and remove any menu options
(<Item>) that the current logged in user does not have roles for.

At the point of reading/parsing the document I have a comma-delimited
string (or ArrayList) of roles assigned to the current user (including
role "All") and so I need to check to see if any of the roles exist in
the AccessRoles attribute for each item.

The problem I am having is in removing the nodes that do not meet the
criteria.

I have been going down the following route (please note that this code
is only checking for the "All" role)...

Public Shared Function GetRoleBasedMenuXml() As String
Dim strMenuXml As String
Dim xmldocMenu As XmlDocument
strMenuXml = HttpContext.Current.Cache.Get("PortMenuXML")

xmldocMenu = New XmlDocument
xmldocMenu.LoadXml(strMenuXml)
Dim xmlnlMenuItem As XmlNodeList =
xmldocMenu.GetElementsByTagName("Item")

For Each xmlNode As XmlNode In xmlnlMenuItem
If Not xmlNode.Attributes("AccessRoles") Is Nothing Then
If xmlNode.Attributes("AccessRoles").Value <> "All" Then
xmlNode.RemoveAll()
xmlNode.RemoveChild(xmlNode.Parent)
End If
End If
Next

Dim swFormattedMenuXML As StringWriter
swFormattedMenuXML = New StringWriter
xmldocMenu.Save(swFormattedMenuXML)
Return swFormattedMenuXML.ToString()
End Function

The problem with this is that the RemoveAll() method only removes the
child nodes and the current node attributes leaving <Item></Item>. I
have tried to use xmlNode.ParentNode.RemoveChild(xmlNode) after the
RemoveAll but this is invalid in a For Each loop! I have spent most of
my day trying to find different ways around this problem (XPath etc.)
but because it is variable depth and also the nature of the AccessRoles
validation it has proved unfruitful - I am missing something!

Any help/suggestions would be greatly appreciated!

Nov 12 '05 #3
Sorry Chris, I have written this incorrectly! As you have suggested I
did use xmlNode.Parent.RemoveChild(xmlNode). But because this is in a
For Each loop this does not work?!

Chris Lovett wrote:
Reverse this call:
xmlNode.RemoveChild(xmlNode.Parent)

To become:
xmlNode.Parent.RemoveChild(xmlNode);

Then you don't even need:
xmlNode.RemoveAll()
"Mikey" <mi*****@sivers.co.uk> wrote in message
news:11**********************@g49g2000cwa.googlegr oups.com...
I have an XML document as follows:

<Menu>
<Group>
<Item Text="About Us" AccessRoles="All">
<Group>
<Item Text="Option 1" AccessRoles="All" />
<Item Text="Option 2" AccessRoles="All" />
<Item Text="Option 3" AccessRoles="All" />
</Group>
</Item>
<Item Text="Projects" AccessRoles="All">
<Group>
<Item Text="Option 1" AccessRoles="All" />
<Item Text="Option 2" AccessRoles="Employee" />
<Item Text="Option 3" AccessRoles="Manager,Executive" />
</Group>
</Item>
<Item Text="Library" AccessRoles="Employee,Manager,Executive">
<Group>
<Item Text="Option 1" AccessRoles="Employee" />
<Item Text="Option 2" AccessRoles="Manager" />
<Item Text="Option 3" AccessRoles="Executive" />
</Group>
</Item>
</Group>
</Menu>

This xml is used for telerik RADMenu component and before I use it with
the control I want to read the document and remove any menu options
(<Item>) that the current logged in user does not have roles for.

At the point of reading/parsing the document I have a comma-delimited
string (or ArrayList) of roles assigned to the current user (including
role "All") and so I need to check to see if any of the roles exist in
the AccessRoles attribute for each item.

The problem I am having is in removing the nodes that do not meet the
criteria.

I have been going down the following route (please note that this code
is only checking for the "All" role)...

Public Shared Function GetRoleBasedMenuXml() As String
Dim strMenuXml As String
Dim xmldocMenu As XmlDocument
strMenuXml = HttpContext.Current.Cache.Get("PortMenuXML")

xmldocMenu = New XmlDocument
xmldocMenu.LoadXml(strMenuXml)
Dim xmlnlMenuItem As XmlNodeList =
xmldocMenu.GetElementsByTagName("Item")

For Each xmlNode As XmlNode In xmlnlMenuItem
If Not xmlNode.Attributes("AccessRoles") Is Nothing Then
If xmlNode.Attributes("AccessRoles").Value <> "All" Then
xmlNode.RemoveAll()
xmlNode.RemoveChild(xmlNode.Parent)
End If
End If
Next

Dim swFormattedMenuXML As StringWriter
swFormattedMenuXML = New StringWriter
xmldocMenu.Save(swFormattedMenuXML)
Return swFormattedMenuXML.ToString()
End Function

The problem with this is that the RemoveAll() method only removes the
child nodes and the current node attributes leaving <Item></Item>. I
have tried to use xmlNode.ParentNode.RemoveChild(xmlNode) after the
RemoveAll but this is invalid in a For Each loop! I have spent most of
my day trying to find different ways around this problem (XPath etc.)
but because it is variable depth and also the nature of the AccessRoles
validation it has proved unfruitful - I am missing something!

Any help/suggestions would be greatly appreciated!


Nov 12 '05 #4
Sorry, there is a mistake in the vb code below...

xmlNode.RemoveChild(xmlNode.Parent) should have read
xmlNode.Parent.RemoveChild(xml*Node) which is in my working code.

I appologise for the diversion!

Mikey wrote:
I have an XML document as follows:

<Menu>
<Group>
<Item Text="About Us" AccessRoles="All">
<Group>
<Item Text="Option 1" AccessRoles="All" />
<Item Text="Option 2" AccessRoles="All" />
<Item Text="Option 3" AccessRoles="All" />
</Group>
</Item>
<Item Text="Projects" AccessRoles="All">
<Group>
<Item Text="Option 1" AccessRoles="All" />
<Item Text="Option 2" AccessRoles="Employee" />
<Item Text="Option 3" AccessRoles="Manager,Executive" />
</Group>
</Item>
<Item Text="Library" AccessRoles="Employee,Manager,Executive">
<Group>
<Item Text="Option 1" AccessRoles="Employee" />
<Item Text="Option 2" AccessRoles="Manager" />
<Item Text="Option 3" AccessRoles="Executive" />
</Group>
</Item>
</Group>
</Menu>

This xml is used for telerik RADMenu component and before I use it with
the control I want to read the document and remove any menu options
(<Item>) that the current logged in user does not have roles for.

At the point of reading/parsing the document I have a comma-delimited
string (or ArrayList) of roles assigned to the current user (including
role "All") and so I need to check to see if any of the roles exist in
the AccessRoles attribute for each item.

The problem I am having is in removing the nodes that do not meet the
criteria.

I have been going down the following route (please note that this code
is only checking for the "All" role)...

Public Shared Function GetRoleBasedMenuXml() As String
Dim strMenuXml As String
Dim xmldocMenu As XmlDocument
strMenuXml = HttpContext.Current.Cache.Get("PortMenuXML")

xmldocMenu = New XmlDocument
xmldocMenu.LoadXml(strMenuXml)
Dim xmlnlMenuItem As XmlNodeList =
xmldocMenu.GetElementsByTagName("Item")

For Each xmlNode As XmlNode In xmlnlMenuItem
If Not xmlNode.Attributes("AccessRoles") Is Nothing Then
If xmlNode.Attributes("AccessRoles").Value <> "All" Then
xmlNode.RemoveAll()
xmlNode.RemoveChild(xmlNode.Parent)
End If
End If
Next

Dim swFormattedMenuXML As StringWriter
swFormattedMenuXML = New StringWriter
xmldocMenu.Save(swFormattedMenuXML)
Return swFormattedMenuXML.ToString()
End Function

The problem with this is that the RemoveAll() method only removes the
child nodes and the current node attributes leaving <Item></Item>. I
have tried to use xmlNode.ParentNode.RemoveChild(xmlNode) after the
RemoveAll but this is invalid in a For Each loop! I have spent most of
my day trying to find different ways around this problem (XPath etc.)
but because it is variable depth and also the nature of the AccessRoles
validation it has proved unfruitful - I am missing something!

Any help/suggestions would be greatly appreciated!


Nov 12 '05 #5
Many thanks for the guidance Dimitre! Is there any chance of an
example? I have not used XSLT before and although I will start looking
at the documentation on msdn library an example for this scenario would
be a great help.
Thanks again!

Nov 12 '05 #6
Just a thought Mike,

instead of trying to delete the node from within the foreach loop which you
say doesn't work,
could you add each node that you want deleted into an ArrayList and then
after the foreach loop go through this Array and do the deleting that you
require?


"Mikey" <mi*****@sivers.co.uk> wrote in message
news:11*********************@f14g2000cwb.googlegro ups.com...
Sorry, there is a mistake in the vb code below...

xmlNode.RemoveChild(xmlNode.Parent) should have read
xmlNode.Parent.RemoveChild(xml*Node) which is in my working code.

I appologise for the diversion!

Nov 12 '05 #7
I have resolved the problem! - It amazing what a new day can do for
clearing the head! :) I just used a Do While Loop instead of the For
Each Loop.

Dim intIndex As Integer = 0
Dim intLimit As Integer = xmlnlMenuItem.Count - 1

Do While intIndex < intLimit
Dim node As XmlNode
node = xmlnlMenuItem.Item(intIndex)
If Not node.Attributes("AccessRoles") Is Nothing Then
If node.Attributes("AccessRoles").Value <> "All" Then
node.ParentNode.RemoveChild(node)
intIndex -= 1
intLimit = xmlnlMenuItem.Count - 1
End If
End If
intIndex += 1
Loop

Thankyou all for you help, I do appreciate it.

Nov 12 '05 #8

"Mikey" <mi*****@sivers.co.uk> wrote in message
news:11*********************@f14g2000cwb.googlegro ups.com...
Many thanks for the guidance Dimitre! Is there any chance of an
example? I have not used XSLT before and although I will start looking
at the documentation on msdn library an example for this scenario would
be a great help.
Thanks again!


Hi Mikey,

This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:user="user:roles"
exclude-result-prefixes="user">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

<user:roles>
<role name="Employee"/>
</user:roles>

<xsl:variable name="vRoles"
select="document('')/*/user:roles/*"/>

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

<xsl:template match="Item">
<xsl:if test=
"$vRoles[contains(current()/@AccessRoles, @name)]
or
current()/@AccessRoles = 'All'">
<xsl:call-template name="identity"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

when applied on your source xml:

<Menu>
<Group>
<Item Text="About Us" AccessRoles="All">
<Group>
<Item Text="Option 1" AccessRoles="All" />
<Item Text="Option 2" AccessRoles="All" />
<Item Text="Option 3" AccessRoles="All" />
</Group>
</Item>
<Item Text="Projects" AccessRoles="All">
<Group>
<Item Text="Option 1" AccessRoles="All" />
<Item Text="Option 2" AccessRoles="Employee" />
<Item Text="Option 3" AccessRoles="Manager,Executive" />
</Group>
</Item>
<Item Text="Library" AccessRoles="Employee,Manager,Executive">
<Group>
<Item Text="Option 1" AccessRoles="Employee" />
<Item Text="Option 2" AccessRoles="Manager" />
<Item Text="Option 3" AccessRoles="Executive" />
</Group>
</Item>
</Group>
</Menu>
produces the wanted result:

<Menu>
<Group>
<Item Text="About Us" AccessRoles="All">
<Group>
<Item Text="Option 1" AccessRoles="All">
</Item>
<Item Text="Option 2" AccessRoles="All">
</Item>
<Item Text="Option 3" AccessRoles="All">
</Item>
</Group>
</Item>
<Item Text="Projects" AccessRoles="All">
<Group>
<Item Text="Option 1" AccessRoles="All">
</Item>
<Item Text="Option 2" AccessRoles="Employee">
</Item>
</Group>
</Item>
<Item Text="Library" AccessRoles="Employee,Manager,Executive">
<Group>
<Item Text="Option 1" AccessRoles="Employee">
</Item>
</Group>
</Item>
</Group>
</Menu>

In the real case the user roles will not be embedded in the stylesheet, but
will be accessible as a separate xml document.
Cheers,
Dimitre Novatchev
Nov 12 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Johannes Lebek | last post by:
Hi there, somehow, I cannot access nodes that are stored in a variable. I'm using Xalan 2.5.1 and the following commands: ================ BEGIN ==================== <xsl:variable...
9
by: Rolf Kemper | last post by:
Dear Experts, I got stuck with the following problem and need your help. What I wnat to do is to get a set of distinct nodes. Before the distinct I have selected the multiple occourences...
2
by: Claudio Jolowicz | last post by:
How can XSLT stylesheets be used to edit, remove and add nodes specified by their position in the document tree? The XML document stores development tasks in a hierarchical way, i.e. tasks can...
3
by: serge calderara | last post by:
Dear all, I have a csv file data which has been read and populate on a dataset object. then I need to bind part of the content of the dataset to a treeview control. I have read that XML format...
1
by: Patrick.O.Ige | last post by:
I have a xml file and i want to format it using XSL My XSL file and XML below I needed to do a distinct which is ok on the first node "Code" For the "programDescription" i did below which gets the...
21
by: James Black | last post by:
I am curious if there is a benefit to set attributes directly, in my javascript, or to use setAttribute. For example, I have this: var input = document.createElementNS(xhtmlNS, 'input');...
0
by: sugarsmack | last post by:
Hi folks, Using XSL, I'm trying to take an XML file containing a flat list of "topics" and generate a hierarchical topic map. The topic nodes include a role attribute that indicates their position...
15
by: CI | last post by:
I have the following XML file <Book> <Chapters> <Chapter number="1"/> <Chapter number="2"/> </Chapters> <Colors> <Color RGB="255"/> <Color RGB="211" name="Red"/>
4
by: N9 | last post by:
Hi I had a xslt that parse a XML document, output is HTML But XSLT adding not valid code: <ul class="level_1" xmlns="" xmlns:xsi="http://www.w3.org/2001/ XMLSchema-instance"> I had try...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: marcoviolo | last post by:
Dear all, I would like to implement on my worksheet an vlookup dynamic , that consider a change of pivot excel via win32com, from an external excel (without open it) and save the new file into a...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.