I have following xml:
<TextWithNodes><Node id="0" />astralis<Node id="8" /> <Node id="9" />ltd<Node id="12" />
<Node id="14" />{<Node id="15" />DOCUMENT<Node id="23" />}<Node id="24" /> <Node id="25" />{<Node id="26" />TYPE<Node id="30" />}<Node id="31" />EX-<Node id="34" />10<Node id="36" />.<Node id="37" />12<Node id="39" /> <Node id="40" />{<Node id="41" />SEQUENCE<Node id="49" />}<Node id="50" />3<Node id="51" /> <Node id="52" />{<Node id="53" />FILENAME<Node id="61" />}<Node id="62" />e<Node id="63" />300201<Node id="69" />_<Node id="70" />ex<Node id="72" />10<Node id="74" />-<Node id="75" />12<Node id="77" />.<Node id="78" />txt<Node id="81" /> </TextWithNodes>
and I need to pick node from Id 25 to id 75. It is a portion of XML. Original XML is very long.
I am using following code:
Dim reader As XmlTextReader = New XmlTextReader(System.Web.HttpContext.Current.Server.MapPath("~/App_Data/gate_xml_output.xml"))
reader.WhitespaceHandling = WhitespaceHandling.None
Dim xmlDoc As XmlDocument = New XmlDocument()
'Load the file into the XmlDocument
xmlDoc.Load(reader)
'Close off the connection to the file.
reader.Close()
Dim nodeList As XmlNodeList = xmlDoc.SelectNodes("//TextWithNodes/node()[preceding-sibling::Node[#id=" & startNode & "] and following-sibling::Node[#id=" & endNode & "]]")
Dim sb As StringBuilder = New StringBuilder
For Each childNode As XmlNode In nodeList
If childNode.Value IsNot Nothing Then
sb.Append(childNode.Value & " ")
End If
Next
' read the text between these nodes
ExtractText = sb.ToString
It is working but It is very slow. Any alternative of getting this data from XML ?
Please suggest.
Thanks
Explore Linq to XML; it should be quicker: http://msdn.microsoft.com/en-us/library/bb387098.aspx
Also good info here: http://www.hookedonlinq.com/LINQtoXML5MinuteOverview.ashx
There's ton of info out there.
Here's an article about performance comparison with xmldoc and xmlreader: http://www.nearinfinity.com/blogs/joe_ferner/performance_linq_to_sql_vs.html
and another: http://msdn.microsoft.com/en-us/library/bb387048.aspx
+1
You could do it with XPath. Like this:
Dim sb As New StringBuilder()
Dim document As New XPathDocument("C:\testfile2.xml")
Dim navigator As XPathNavigator = document.CreateNavigator()
Dim iterator As XPathNodeIterator = navigator.Select("yourPath")
While iterator.MoveNext()
sb.Append(iterator.Current.Value)
End While
You can find more information here
The evaluation of this XPath expression has only O(N) complexity (linear) vs. O(N^2) for your original XPath expression:
/*/Node[#id >= 15 and not(#id > 75)]
This selects any Node element that is a child of the top element of the XML document and the value of whose id attribute is between the two specified lower and upper limits: respectively 15 and 75.
Here we assume that the values of the id attributes of Node elements are monotonously increasing -- exactly as in the provided XML document.
XSLT - based verification:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select=
"/*/Node[#id >= 15 and not(#id > 75)]"/>
</xsl:template>
</xsl:stylesheet>
when this transformation is performed on the provided XML document:
<TextWithNodes>
<Node id="0" />astralis
<Node id="8" />
<Node id="9" />ltd
<Node id="12" />
<Node id="14" />{
<Node id="15" />DOCUMENT
<Node id="23" />}
<Node id="24" />
<Node id="25" />{
<Node id="26" />TYPE
<Node id="30" />}
<Node id="31" />EX-
<Node id="34" />10
<Node id="36" />.
<Node id="37" />12
<Node id="39" />
<Node id="40" />{
<Node id="41" />SEQUENCE
<Node id="49" />}
<Node id="50" />3
<Node id="51" />
<Node id="52" />{
<Node id="53" />FILENAME
<Node id="61" />}
<Node id="62" />e
<Node id="63" />300201
<Node id="69" />_
<Node id="70" />ex
<Node id="72" />10
<Node id="74" />-
<Node id="75" />12
<Node id="77" />.
<Node id="78" />txt
<Node id="81" />
</TextWithNodes>
the XPath expression is evaluated and the selected nodes are output:
<Node id="15"/>
<Node id="23"/>
<Node id="24"/>
<Node id="25"/>
<Node id="26"/>
<Node id="30"/>
<Node id="31"/>
<Node id="34"/>
<Node id="36"/>
<Node id="37"/>
<Node id="39"/>
<Node id="40"/>
<Node id="41"/>
<Node id="49"/>
<Node id="50"/>
<Node id="51"/>
<Node id="52"/>
<Node id="53"/>
<Node id="61"/>
<Node id="62"/>
<Node id="63"/>
<Node id="69"/>
<Node id="70"/>
<Node id="72"/>
<Node id="74"/>
<Node id="75"/>
Related
I'm trying to write a graph to a file but I'm getting a different node labels than I would like.
Example Code:
g <- graph.star(2)
V(g)$name <- c('homer','marge')
write.graph(g,file = 'g.graphml',format = 'graphml')
Output:
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<!-- Created by igraph -->
<key id="g_name" for="graph" attr.name="name" attr.type="string"/>
<key id="g_mode" for="graph" attr.name="mode" attr.type="string"/>
<key id="g_center" for="graph" attr.name="center" attr.type="double"/>
<key id="v_name" for="node" attr.name="name" attr.type="string"/>
<graph id="G" edgedefault="directed">
<data key="g_name">In-star</data>
<data key="g_mode">in</data>
<data key="g_center">1</data>
<node id="n0"> ###### This should <node id = "homer">
<data key="v_name">homer</data>
</node>
<node id="n1"> ###### This should <node id = "marge">
<data key="v_name">marge</data>
</node>
<edge source="n1" target="n0">
</edge>
</graph>
</graphml>
I would like the "node id" attribute to be the names of the nodes (as shown in comments). Anybody have any ideas? Thanks!
You can't do this currently AFAIK. I am not sure why it is not implemented that way. Can you please open an issue about it at https://github.com/igraph/igraph/issues?state=open ? Thanks.
I'd like to change icon of the node according to the attribute automatically/dynamically in Flex.
Bellow are my codes:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="540" height="610" chromeColor="#E8E50A">
<fx:Declarations>
<fx:XMLList id="user_list">
<node user="Running Center">
<node user="System Administrator">
<node icon="admin" user="admin" type="admin"/>
<node icon="home" user="root" type="home"/>
</node>
<node user="Common User">
<node icon="user" user="Udo" type="user"/>
<node icon="user" user="Steven" type="user"/>
<node icon="user" user="Peter" type="user"/>
</node>
</node>
</fx:XMLList>
</fx:Declarations>
<fx:Script>
<![CDATA[
[Bindable]
[Embed(source="assets/admin.png")]
public var admin:Class;
[Bindable]
[Embed(source="assets/home.png")]
public var home:Class;
[Bindable]
[Embed(source="assets/user.png")]
public var user:Class;
]]>
</fx:Script>
<mx:Tree id="user_tree"
x="10" y="51" width="206"
height="207" dataProvider="{user_list}"
iconField="#icon" labelField="#user" showRoot="true" />
</s:Application>
Here is the effect image:
I'm sorry for I can't post an image.
Bellow is the link.
http://i.stack.imgur.com/oZG6v.jpg
For example,maybe I should change the code like this?
<node icon="{...}" user="admin" type="admin"/>
Any help is greetful. Thanks in advance.
Here are some Google results for: "Flex tree iconFunction"
http://blog.flexexamples.com/2007/11/15/creating-a-custom-icon-function-on-a-flex-tree-control/
http://blog.flexexamples.com/2007/11/15/setting-a-custom-icon-field-in-a-flex-tree-control/
My xml looks like this:
<node label=home>
<node label="1.0" >
<node label="1.1">
<node label="1.1.1">
<node label="1.1.1.1"/>
<node label="1.1.1.2"/>
</node>
<node label="1.1.2"/>
<node label="1.1.3"/>
</node>
<node label="1.2"/>
<node label="1.3">
<node label="1.3.1"/>
<node label="1.3.2"/>
</node>
</node>
<node label="2.0"/>
</node>
I have 4 columns in my datagrid.
1st col should get only data which is as 1.0 and 2.0.
2nd col should get data as 1.1.
3rd col as 1.1.1.
4th col as 1.1.1.1,and so on.
Any idea how I can do this?
First of all, shouldn't the "2.0" node be on the same level as "1.0" node? (In your sample the "2.0" node is inside "1.0" node).
Second, I'm not sure if this is what you are looking for but try this sample application and let me know if it helps.
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%"
height="100%">
<mx:Script>
<![CDATA[
private function labelBuilder(item:Object, column:DataGridColumn):String {
var ref:Object = this.deriveComplexColumnData(item, column.dataField);
var label:String = "";
for (var r:String in ref) {
label += ref[r] + "; ";
}
return label;
}
private function deriveComplexColumnData(data:Object, dataField:String):Object {
var currentRef:Object = data;
var tokens:Array = dataField.split('.');
if (tokens.length > 0) {
for (var i:int = 0; i < tokens.length; i++)
currentRef = currentRef[tokens[i]];
}
return currentRef;
}
]]>
</mx:Script>
<mx:XML id="xml">
<node label="home">
<node label="1.0">
<node label="1.1">
<node label="1.1.1">
<node label="1.1.1.1"/>
<node label="1.1.1.2"/>
</node>
<node label="1.1.2"/>
<node label="1.1.3"/>
</node>
<node label="1.2"/>
<node label="1.3">
<node label="1.3.1"/>
<node label="1.3.2"/>
</node>
</node>
<node label="2.0"/>
</node>
</mx:XML>
<mx:DataGrid id="dg" width="100%" height="100%" dataProvider="{xml.node}">
<mx:columns>
<mx:DataGridColumn dataField="#label" headerText="Node1"/>
<mx:DataGridColumn dataField="node.#label" headerText="Node2"/>
<mx:DataGridColumn dataField="node.node.#label" headerText="Node3"/>
<mx:DataGridColumn dataField="node.node.node.#label" labelFunction="{ labelBuilder }" headerText="Node4"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
Note the "dataField" in each DataGridColum, each "node." represents 1 depth level inside the XML.
I've also added a labelBuilder method just to help you understand how the data is being processed and how you can change the way it is being rendered.
use formatters.....
<mx:Script>
<![CDATA[
// Event handler to format the input.
private function Format():void
{
// The format() method returns the formatted String,
// or an empty String if there is an error.
var formattedVal:String = numberFormatter.format(inputVal.text);
if (formattedVal.length==0) {
// If there is an error, the Format.error property
// contains the reason.
formattedNumber.text=numberFormatter.error;
}
else {
formattedNumber.text=formattedVal;
}
}
]]>
</mx:Script>
<mx:NumberFormatter id="numberFormatter"/>
<mx:Panel title="NumberFormatter Example" width="75%" height="75%"
paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10">
<mx:Form>
<mx:FormItem label="Enter number - a letter is invalid:">
<mx:TextInput id="inputVal" text="" width="75%"/>
</mx:FormItem>
<mx:FormItem label="Formatted number: ">
<mx:TextInput id="formattedNumber" editable="false" width="75%"/>
</mx:FormItem>
<mx:FormItem>
<mx:Button label="Validate and Format" click="Format();"/>
</mx:FormItem>
</mx:Form>
</mx:Panel>
i hope this will be good enough:-)
you can get an idea from this and modify for ur requirement....cya!
You want to get those nodes into grid based on their level in xml - level N goes into column N. You can determine this level by counting parents until it's null:
public static function getNestLevel(node:XML):int {
var level:int = 0;
while (node.parent()) {
level++;
node = node.parent();
}
return level;
}
I think, you need to prepare data structure for you grid and put nodes there using their levels. You didn't say anything about rows. Do you want each row like 1.0 | 1.1 | 1.1.1 or each node on different row?
I have an xml as a string in flex in the below format.
I can have as many nested groups and test as possible.
I need a way to find which are checked, how can I iterate through this?
<node label="All" checked="0">
<node label="Group1" checked="0">
<node label="Test1" checked="0" />
<node label="Test2" checked="0" />
<node label="Group1Inner" checked="0">
<node label="Test1Inner" checked="0" />
<node label="Test2Inner" checked="0" />
</node>
<node label="Group2Inner" checked="0">
<node label="Test1Inner" checked="0" />
<node label="Test2Inner" checked="0" />
</node>
</node>
</node>
You can manage this by using E4X
var xx:XML = <node label="All" checked="0">
<node label="Group1" checked="0">
<node label="Test1" checked="0" />
<node label="Test2" checked="0" />
<node label="Group1Inner" checked="0">
<node label="Test1Inner" checked="0" />
<node label="Test2Inner" checked="0" />
</node>
<node label="Group2Inner" checked="0">
<node label="Test1Inner" checked="0" />
<node label="Test2Inner" checked="0" />
</node>
</node>
</node>;
trace(xx..node.(#checked==0))
In a Flex application, I'm have an xml object that I'm binding to a tree control. I'm able to add a child node to the xml but when I try to add a child to the child node it doesn't appear on the tree control
tree = <node label="Root">
<node label="Category 1"/>
<node label="Category2"/>
<node label="Category3"/>
<node label="Category 4">
<node label="SubCategory4.1"/>
<node label="SubCategory4.2"/>
</node>
</node>;
var someNode:XMLNode = new XMLNode(9, 'Category5');
var aSubNode:XMLNode = new XMLNode(9, 'SubCategory5.1');
someNode.appendChild(aSubNode);
tree.appendChild(someNode);
So Category5 appears on the tree control but SubCategory5.1 does not. What am I missing?
If you are using flex, use AS3. XMLNode is AS2. In short, try this:
tree = <node label="Root">
<node label="Category 1"/>
<node label="Category2"/>
<node label="Category3"/>
<node label="Category 4">
<node label="SubCategory4.1"/>
<node label="SubCategory4.2"/>
</node>
</node>;
var someNode:XML = <node label="Category5"/>;
var aSubNode:XML = <node label="SubCategory5.1"/>;
someNode.appendChild(aSubNode);
tree.appendChild(someNode);