Parsing XML documents iOS - ios

I have to parse this document and I plan on using NSXMLparser but the only problem is I do not know how to get the information I want. I don't know how to navigate through each tag, I have seen simple examples but when I try to use their method I get random tags and information I don't want. Can someone explain how to get certain information from a complex XML structure such as this one?
Thanks!
<kml xmlns:ns3="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:ns2="http://www.w3.org/2005/Atom"
xmlns="http://www.opengis.net/kml/2.2">
<Document>
<description>Available CAR2GO Vehicles</description>
<Style id="car2go">
<IconStyle>
<Icon>
<href>http://www.car2go.com/common/images/openapi/marker_car2go.png
</href>
</Icon>
<hotSpot y="0.0" x="0.0" />
</IconStyle>
</Style>
<Style id="car2go_ed">
<IconStyle>
<Icon>
<href>http://www.car2go.com/common/images/openapi/marker_car2go_ed.png
</href>
</Icon>
<hotSpot y="0.0" x="0.0" />
</IconStyle>
</Style>
<Placemark>
<name>UL-C5887</name>
<description>Sudetenweg, 89075 Ulm<br/>Fuel
24<br/>Interior GOOD<br/>Exterior GOOD
</description>
<styleUrl>#car2go_ed</styleUrl>
<ExtendedData>
<Data name="fuel">
<value>24</value>
</Data>
<Data name="interior">
<value>GOOD</value>
</Data>
<Data name="exterior">
<value>GOOD</value>
</Data>
<Data name="vin">
<value>WME4513001K154655</value>
</Data>
<Data name="engineType">
<value>ED</value>
</Data>
<Data name="charging">
<value>true</value>
</Data>
</ExtendedData>
<Point>
<coordinates>10.029,48.4362,0</coordinates>
</Point>
</Placemark>
<Placemark>
<name>UL-C5889</name>
<description>Heilmeyersteige, 89075 Ulm<br/>Fuel
58<br/>Interior GOOD<br/>Exterior GOOD
</description>
<styleUrl>#car2go</styleUrl>
<ExtendedData>
<Data name="fuel">
<value>58</value>
</Data>
<Data name="interior">
<value>GOOD</value>
</Data>
<Data name="exterior">
<value>GOOD</value>
</Data>
<Data name="vin">
<value>WME4513001K154655</value>
</Data>
<Data name="engineType">
<value>CE</value>
</Data>
</ExtendedData>
<Point>
<coordinates>9.947235,48.410497,0</coordinates>
</Point>
</Placemark>
</Document>

I get random tags and information I don't want
With NSXMLParser you don't navigate through the XML. Instead, you create a delegate for the parser that gets messages each time the parser encounters something -- a tag, a value, etc. Your delegate needs to watch for the tags and values that it's interested in and do whatever makes sense for your app when those arrive. So, the tags you're seeing aren't random, they're just the tags from the file you're parsing in the order in which they appear in the file.
Can someone explain how to get certain information from a complex XML structure such as this one?
Generally, your parser delegate will be a little like a state machine that keeps track of which tag it's parsing, what data it sees, etc. That may be more than you're up for, in which case you might want to look into other XML parsing options than NSXMLParser. TouchXML is one library that's popular because it parses the file for you and then lets you look through the data with Xquery.

I would highly suggest you do not reinvent the wheel and use a high level 3rd party library which will make your life a ton easier. #mattt of AFNetworking fame amongst others has an excellent XML parsing library called Ono.

I suggest you examine the strategy demonstrated by Apple's own example code here:
https://developer.apple.com/library/ios/samplecode/SeismicXML/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007323
The actual parsing code is here:
https://developer.apple.com/library/ios/samplecode/SeismicXML/Listings/SeismicXML_APLParseOperation_m.html#//apple_ref/doc/uid/DTS40007323-SeismicXML_APLParseOperation_m-DontLinkElementID_11
All the work is done by the parser's delegate (which is this object, self). Notice in particular how didStartElement:... makes choices depending on what kind of element has just been encountered.
I should also mention that there is another strategy, where instead of the delegate making these choices, you keep repointing the parser at a different delegate. Here, I develop a general version of that strategy and show how to adapt it to a particular parsing situation: http://www.apeth.com/iOSBook/ch36.html#_xml

Related

Gremlin: Read edge GraphML file and node GraphML file in separate queries

I have two files that I want to load by using g.io(<name file>).read().iterate(): nodes.xml and edges.xml.
The nodes.xml file contains the nodes of the graph I want to upload, and its contents are this:
<?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">
<key id="labelV" for="node" attr.name="labelV" attr.type="string" />
<key id="name" for="node" attr.name="name" attr.type="string" />
<key id="age" for="node" attr.name="age" attr.type="int" />
<graph id="G" edgedefault="directed">
<node id="1">
<data key="labelV">person</data>
<data key="name">marko</data>
<data key="age">29</data>
</node>
<node id="2">
<data key="labelV">person</data>
<data key="name">vadas</data>
<data key="age">27</data>
</node>
</graph>
</graphml>
The edges.xml file contains the edges of the graph I want to upload, and its content are this:
<?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">
<key id="labelE" for="edge" attr.name="labelE" attr.type="string" />
<key id="weight" for="edge" attr.name="weight" attr.type="double" />
<graph id="G" edgedefault="directed">
<edge id="7" source="1" target="2">
<data key="labelE">knows</data>
<data key="weight">0.5</data>
</edge>
</graph>
</graphml>
I want to upload the nodes first by running g.io('nodes.xml').read().iterate() and then the edges by running g.io('edges.xml').read().iterate(). But when I upload the edges.xml, instead of adding edges to the previously created nodes, it creates new nodes.
It is possible to easily load the nodes first and then the edges in separate queries with a similar command in Gremlin? I know this can be accomplished with complex queries that involve reading and creating edge by edge the edges in the edges.xml file via user queries, but I'm wondering if there is something easier. Also, I wouldn't want to upload a single file with all the nodes and edges.
I'm afraid that the GraphMLReader doesn't work that way. It's not designed to read into an existing graph. I honestly can't remember if this was done purposefully or not.
The code isn't too complicated though. You could probably just modify it to work they way that you want. You can see here where the code checks the vertex cache for the id. That cache is empty on your second execution because it is only filled by way of new vertex additions - it doesn't remember any from your first run and it doesn't read from the graph directly for your second run. Simply change that to logic to better suit your needs.

Specify an edgeLabel in graphML that tinkerpop can understand

I have been struggling to load a graphml in to Tinkerpop3.
Graph graphMLGraph = TinkerGraph.open();
graphMLGraph.io(IoCore.graphml()).readGraph(file.getAbsolutePath());
While loading, I want the the edges to have a label.
graphTraversalSource.E().toStream().forEach(edge -> {
System.out.println(edge.label());
});
The above code always prints the labels as edge for all the edges in the graphml. My graphml snippets.
<edge id="1" source="1" target="3">
<data key="edgelabel">belongs-to</data>
<data key="weight">1.0</data>
</edge>
<edge id="2" source="1" target="4">
<data key="weight">1.0</data>
<data key="edgelabel">part-of</data>
</edge>
And the key definition
<key attr.name="Edge Label" attr.type="string" for="edge" id="edgelabel"/>
I am use DSE 5.1.3's java driver and tinkerpop 3.2.5 is used via a transitive dependency and used Gephi to author the graphml.
By default, your edge label will be recognized if you do define the key as:
<key id="labelE" for="edge" attr.name="labelE" attr.type="string" />
The important part being that the attr.name is defaulted to "labelE". See the IO Reference documentation for GraphML here. Note that the default can be changed when you instantiate the GraphMLReader.Builder object by setting the edgeLabelKey value on the builder itself.

Parse HTML stored as string in Database in ColdFusion

I have taken over this ColdFusion project and found that I need a value out of a database field that includes HTML. The field data looks like this (without the new lines):
<wddxPacket version="1.0">
<header />
<data>
<struct>
<var name="en">
<string>3 Nights' Lodging</string>
</var>
<var name="sp">
<string>3 Noches alojamiento</string>
</var>
</struct>
</data>
</wddxPacket>
I am wanting to use this data but I only need the text between the:
<var name='en'><string>3 Nights' Lodging</string></var>
I used a function that ColdFusion has to remove HTML:
#REReplaceNoCase(pkg.title, "<[^><]*>", '', 'ALL')#
But when I use that, I get something like this:
3 Nights' Lodging3 Noches alojamiento
All I want is:
3 Nights' Lodging
Examining the beginning of the string, ie <wddxPacket ...> it is actually WDDX.
If you do a search for ColdFusion + WDDX you will find the documentation for CFWDDX. It is a built in tag which supports conversions of WDDX strings to CFML objects (and vice versa) for easier manipulation. In your case use action="wddx2cfml" to convert the string back into a CF structure.
<cfwddx action="wddx2cfml" input="#text#" output="result">
<cfdump var="#result#" label="Raw object">
Then use the key #result.en# to grab the string you want.

BiosInitTime from Hibernate Resume ETW trace

Looking at the "BiosInitTime" from ETW events parsed using "tracerpt.exe" and I noticed for hibernate/S4 resume it's always 0 (see example at the end). The same happened with etl traces collected directly using XPERF or via ADK Windows Assessment Console. But via WAC/WPA analysis & GUI, the BIOS will be shown. So it appears the information is there but "tracerpt.exe" is parsing the wrong events to calculate "BiosInitTime".
What specific start/stop events I should check to calculate the Bios Init Time via etl trace, say, using xperf?
Thanks
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Kernel-Power" Guid="{331c3b3a-2005-44c2-ac5e-77220c37d6b4}" />
<EventID>39</EventID>
<Version>0</Version>
<Level>4</Level>
<Task>33</Task>
<Opcode>0</Opcode>
<Keywords>0x400000000000000C</Keywords>
<TimeCreated SystemTime="2016-02-03T15:08:43.601479000Z" />
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />
<Execution ProcessID="4" ThreadID="3140" ProcessorID="0" KernelTime="180" UserTime="0" />
<Channel>Microsoft-Windows-Kernel-Power/Diagnostic</Channel>
<Computer />
</System>
<EventData>
<Data Name="SleepTime"> 1546</Data>
<Data Name="ResumeTime"> 769</Data>
<Data Name="DriverWakeTime"> 715</Data>
<Data Name="HiberWriteTime"> 2999</Data>
<Data Name="HiberReadTime"> 1862</Data>
<Data Name="HiberPagesWritten"> 148964</Data>
**<Data Name="BiosInitTime"> 0</Data>**
</EventData>
<RenderingInfo Culture="en-US">
<Level>Information </Level>
<Opcode>Info </Opcode>
<Keywords>
<Keyword>po:Diagnostic</Keyword>
<Keyword>po:Performance</Keyword>
</Keywords>
<Task>PowerTransition</Task>
<Channel>Microsoft-Windows-Kernel-Power/Diagnostic</Channel>
<Provider>Microsoft-Windows-Kernel-Power </Provider>
</RenderingInfo>
The Microsoft-Windows-Kernel-Power events are not captured into the ETL when selecting hibernation in WPRUI.exe. You can see this if you open the ETL with PerfView and look in the raw event list.
So when you try to search for the BiosInitTime it shows as 0. If you can see if when running the ADK Windows Assessment Console, this means here the Microsoft-Windows-Kernel-Power events are captured.

parseKml() error

I have noticed that parseKml() function does not parse KML file correctly. For example, if you have this bit of KML:
<ExtendedData>
<Data name="Offer">
<value>Apples</value>
<value>Potatoes</value>
<value>Tomatoes</value>
</Data>
</ExtendedData>
The parseKml() function will return a kmlObject that will contain only the last value, i.e. "Tomatoes":
Does anyone have a solution for this?
The structure for the type of extended data you are using is for name/value pairs. i.e. a single name with a single value.
<ExtendedData>
<Data name="string">
<displayName>...</displayName> <!-- string -->
<value>...</value> <!-- string -->
</Data>
</ExtendedData>
So what you are trying will not work. If you wish to add an arbitrary XML Data structure to a KML Feature then you would do it like this.
<ExtendedData xmlns:offer="http://yourserver.com/namespace">
<offer:item>Apples</offer:item>
<offer:item>Potatoes</offer:item>
<offer:item>Tomatoes</offer:item>
</ExtendedData>
Based on the data structure, the 'offer' XML Schema file (http://yourserver.com/namespace) would be something like.
<?xml version="1.0" encoding="utf-16"?>
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="item" type="xsd:string" />
</xsd:schema>
I believe the <Data> element can only contain a single <value> - according to the docs, the "<Data> element allows you to add untyped name/value pairs to the user data associated with a given Feature."
So in your case, it's picking up the last <value> element only. You might find another way to add your custom data here: https://developers.google.com/kml/documentation/extendeddata

Resources