I'm completly new to XML, libxml and xpath. Therefore I wanted to parse a very simple XML expression
<count>
<active type="integer">1</active>
</count>
I want to retrieve the value 1. I wrote the following code that uses libxml (this code contains objective c code):
const unsigned char* xPathExp = (const unsigned char*) "count/active/text()";
xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression( xPathExp, xpathCtx);
xmlNodeSetPtr nodeSetPtr = xpathObj->nodesetval;
if( nodeSetPtr != 0 ) {
xmlNode* node = nodeSetPtr->nodeMax > 0 ? nodeSetPtr->nodeTab[0] : 0;
if( node != 0 ) {
NSLog(#"Active Projects = %#", [self stringFromCString:node->name] );
} else {
NSLog(#"Node for xpath Exp: count/active/text() does not exist.");
}
} else
NSLog(#"nodeSetPtr is null");
xmlFreeDoc(doc);
xmlCleanupParser();
It turns out that the output of this code is
nodeSetPtr is null
So that confuses me. I ran an online xpath evaluator on the xml above and the xpath expression "count/active/text()" return 1.
What am I doing wrong here?
It may be as simple as your document setup and what the root element is. first, try //count/active/text(). If that works, then try /count/active/text(). In general, try not to use // unless you really want to match anywhere (great for debugging this particular problem, though). /count should find the count element against the root.
Related
This code is for Aho-Corasick algorithm which i have refereed from here
I understood this code up to if block of push_links method but i didn't get the use or requirement for the else part of the same method.
More specifically first method is used for the construction of trie. The remaining work is done by second method i.e linking the node to their longest proper suffix which are prefix of some pattern also. This is carried out by the If block then what is the need of else part.
Please help me in this.
const int MAXN = 404, MOD = 1e9 + 7, sigma = 26;
int term[MAXN], len[MAXN], to[MAXN][sigma], link[MAXN], sz = 1;
// this method is for constructing trie
void add_str(string s)
{
// here cur denotes current node
int cur = 0;
// this for loop adds string to trie character by character
for(auto c: s)
{
if(!to[cur][c - 'a'])
{
//here two nodes or characters are linked using transition
//array "to"
to[cur][c - 'a'] = sz++;
len[to[cur][c - 'a']] = len[cur] + 1;
}
// for updating the current node
cur = to[cur][c - 'a'];
}
//for marking the leaf nodes or terminals
term[cur] = cur;
}
void push_links()
{
//here queue is used for breadth first search of the trie
int que[sz];
int st = 0, fi = 1;
//very first node is enqueued
que[0] = 0;
while(st < fi)
{
// here nodes in the queue are dequeued
int V = que[st++];
// link[] array contains the suffix links.
int U = link[V];
if(!term[V]) term[V] = term[U];
// here links for the other nodes are find out using assumption that the
// link for the parent node is defined
for(int c = 0; c < sigma; c++)
// this if condition ensures that transition is possible to the next node
// for input 'c'
if(to[V][c])
{
// for the possible transitions link to the reached node is assigned over
// here which is nothing but transition on input 'c' from the link of the
// current node
link[to[V][c]] = V ? to[U][c] : 0;
que[fi++] = to[V][c];
}
else
{
to[V][c] = to[U][c];
}
}
}
IMO you don't need the else-condition. If there is no children either it's already a link or nothing.
There are some variations of Aho-Corasick algorithm.
Base algorithm assumes that if edge from current node (cur) over symbol (c) is missing, then you go via suffix links to the first node that has edge over c (you make move via this edge).
But your way over suffix links is the same (from the same cur and c), because you don't change automaton while searching. So you can cache it (save result of
// start from node
while (parent of node doesn't have an edge over c) {
node = parent
}
// set trie position
node = to[node][c]
// go to next character
in to[node][c]. So next time you won't do this again. And it transfrom automaton from non-deterministic into deterministic state machine (you don't have to use link array after pushing, you can use only to array).
There are some problems with this implementation. First, you can get an index of string you found (you don't save it). Also, len array isn't used anywhere.
For
means, this algorithm is just checking the existence of the character in the current node link using "link[to[V][c]] = V ? to[U][c] : 0;". should not it verify in the parents link also?
Yes, it's ok, because if to[U][c] is 0, then there are no edges via c from all chain U->suffix_parent->suffix parent of suffix_parent ... -> root = 0. So you should set to[V][c] to zero.
I want to keep white space when I call text attribute of token, is there any way to do it?
Here is the situation:
We have the following code
IF L > 40 THEN;
ELSE
IF A = 20 THEN
PUT "HELLO";
In this case, I want to transform it into:
if (!(L>40){
if (A=20)
put "hello";
}
The rule in Antlr is that:
stmt_if_block: IF expr
THEN x=stmt
(ELSE y=stmt)?
{
if ($x.text.equalsIgnoreCase(";"))
{
WriteLn("if(!(" + $expr.text +")){");
WriteLn($stmt.text);
Writeln("}");
}
}
But the result looks like:
if(!(L>40))
{
ifA=20put"hello";
}
The reason is that the white space in $stmt was removed. I was wondering if there is anyway to keep these white space
Thank you so much
Update: If I add
SPACE: [ ] -> channel(HIDDEN);
The space will be preserved, and the result would look like below, many spaces between tokens:
IF SUBSTR(WNAME3,M-1,1) = ')' THEN M = L; ELSE M = L - 1;
This is the C# extension method I use for exactly this purpose:
public static string GetFullText(this ParserRuleContext context)
{
if (context.Start == null || context.Stop == null || context.Start.StartIndex < 0 || context.Stop.StopIndex < 0)
return context.GetText(); // Fallback
return context.Start.InputStream.GetText(Interval.Of(context.Start.StartIndex, context.Stop.StopIndex));
}
Since you're using java, you'll have to translate it, but it should be straightforward - the API is the same.
Explanation: Get the first token, get the last token, and get the text from the input stream between the first char of the first token and the last char of the last token.
#Lucas solution, but in java in case you have troubles in translating:
private String getFullText(ParserRuleContext context) {
if (context.start == null || context.stop == null || context.start.getStartIndex() < 0 || context.stop.getStopIndex() < 0)
return context.getText();
return context.start.getInputStream().getText(Interval.of(context.start.getStartIndex(), context.stop.getStopIndex()));
}
Looks like InputStream is not always updated after removeLastChild/addChild operations. This solution helped me for one grammar, but it doesn't work for another.
Works for this grammar.
Doesn't work for modern groovy grammar (for some reason inputStream.getText contains old text).
I am trying to implement function name replacement like this:
enterPostfixExpression(ctx: PostfixExpressionContext) {
// Get identifierContext from ctx
...
const token = CommonTokenFactory.DEFAULT.createSimple(GroovyParser.Identifier, 'someNewFnName');
const node = new TerminalNode(token);
identifierContext.removeLastChild();
identifierContext.addChild(node);
UPD: I used visitor pattern for the first implementation
Here's the ugly long code:
var i;
if(true)
i = 1;
else
i = 0;
When I try this:
var i = (true ? 0 : 1);
it doesn't work resulting in an error on the following line. I guess I was a bit inattentive reading Dart's syntax specs, so can anybody show me the right way?
This looks perfectly fine from a syntax point of view. You can omit the parentheses.
I get a warning 'Dead code' at '1' with your example because of 'true'.
The Darteditor shows you a hint that you wrote code that may contain a bug because he knows your expression can never evaluate to 1 because of the hardcoded 'true'.
void main(List<String> args) {
var b = true;
var i = b ? 0 : 1;
}
doesn't produce a warning.
I am using libclang to parse a objective c source code file. The following code finds all Objective-C instance method declarations, but it also finds declarations in the includes:
enum CXCursorKind curKind = clang_getCursorKind(cursor);
CXString curKindName = clang_getCursorKindSpelling(curKind);
const char *funcDecl="ObjCInstanceMethodDecl";
if(strcmp(clang_getCString(curKindName),funcDecl)==0{
}
How can I skip everything, which comes from header includes? I am only interested in my own Objective-C instance method declarations in the source file, not in any of the includes.
e.g. the following should not be included
...
Location: /System/Library/Frameworks/Foundation.framework/Headers/NSObject.h:15:9:315
Type:
TypeKind: Invalid
CursorKind: ObjCInstanceMethodDecl
...
Answering this question because I couldn't believe that hard-coding paths comparisons was the only solution, and indeed, there is a clang_Location_isFromMainFile function that does exactly what you want, so that you can filter unwanted results in the visitor, like this :
if (clang_Location_isFromMainFile (clang_getCursorLocation (cursor)) == 0) {
return CXChildVisit_Continue;
}
The only way I know would be to skip unwanted paths during the AST visit. You can for example put something like the following in your visitor function. Returning CXChildVisit_Continue avoids visiting the entire file.
CXFile file;
unsigned int line, column, offset;
CXString fileName;
char * canonicalPath = NULL;
clang_getExpansionLocation (clang_getCursorLocation (cursor),
&file, &line, &column, &offset);
fileName = clang_getFileName (file);
if (clang_getCString (fileName)) {
canonicalPath = realpath (clang_getCString (fileName), NULL);
}
clang_disposeString (fileName);
if (strcmp(canonicalPath, "/canonical/path/to/your/source/file") != 0) {
return CXChildVisit_Continue;
}
Also, why compare CursorKindSpelling instead of the CursorKind directly?
I override object's -(NSString*)description however Xcode always displays error: summary string parsing error in summary field in variables view.
My current implementation is the following:
- (NSString*)description {
return [NSString stringWithFormat:#"<%# %p> x=%f, y=%f", self.class, self, _x, _y];
}
If I type po objectName in console, LLDB shows a fine output as expected, however Xcode and command p objectName always indicate error, so what's the proper debug description format to make summary field work? Worth to notice that the output of "p" command is the same as a summary message that you see in Xcode for instances of Foundation classes.
Update:
As far as I can see from "WWDC 2012 session Debugging in Xcode", custom summaries can be implemented using Custom python script only. -(NSString*)description or -(NSString*)debugDescription methods are not connected anyhow to summary messages. I thought they are because I got an error displayed, but it seems it's a standard message for classes that do not have their own formatters.
I would suggest at least:
- (NSString*)description {
return [NSString stringWithFormat:#"%#; x=%f, y=%f", [super description], _x, _y];
}
So that you're not manually replicating the NSObject default and thereby blocking any non-default behaviour your superclass may have opted to include.
Beyond that, "summary string parsing error" is an lldb error. It's being reported by the debugger only. Per its documentation, po is correct for Objective-C objects; p is for C or C++ objects. So you needn't heed that error — it's essentially just telling you that you used the wrong lldb command.
EDIT: for what it's worth, the method used by CFArray is open source and looks like:
static CFStringRef __CFArrayCopyDescription(CFTypeRef cf) {
CFArrayRef array = (CFArrayRef)cf;
CFMutableStringRef result;
const CFArrayCallBacks *cb;
CFAllocatorRef allocator;
CFIndex idx, cnt;
cnt = __CFArrayGetCount(array);
allocator = CFGetAllocator(array);
result = CFStringCreateMutable(allocator, 0);
switch (__CFArrayGetType(array)) {
case __kCFArrayImmutable:
CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = immutable, count = %u, values = (%s"), cf, allocator, cnt, cnt ? "\n" : "");
break;
case __kCFArrayDeque:
CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = mutable-small, count = %u, values = (%s"), cf, allocator, cnt, cnt ? "\n" : "");
break;
}
cb = __CFArrayGetCallBacks(array);
for (idx = 0; idx < cnt; idx++) {
CFStringRef desc = NULL;
const void *val = __CFArrayGetBucketAtIndex(array, idx)->_item;
if (NULL != cb->copyDescription) {
desc = (CFStringRef)INVOKE_CALLBACK1(cb->copyDescription, val);
}
if (NULL != desc) {
CFStringAppendFormat(result, NULL, CFSTR("\t%u : %#\n"), idx, desc);
CFRelease(desc);
} else {
CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p>\n"), idx, val);
}
}
CFStringAppend(result, CFSTR(")}"));
return result;
}
As with the other comments above, I'm willing to gamble that the answer is: Xcode's debugger isn't smart in any sense and definitely isn't smart enough to use the correct po means of getting an Objective-C description; if your object is an uninflected Objective-C object then the debugger isn't going to be able to figure it out.