What is an alternative to this XPath //div[#id='foo'] in GPath? In general, where I can find this documentation?
Here is the corresponding snippet:
def node = new XmlSlurper().parseText(...)
def foo = node.depthFirst().findAll { it.name() == 'div' && it.#id == 'foo'}
A few other links you may want to read:
GPath documentation
Processing XML with Groovy
The previous poster gave you all that's required: Assuming your document has been slurped into xml, you want
def foo = xml.path.to.div.find{it.#id == 'foo'}
to find a single result. Or findAll to find all results.
To mimic the expression //div[#id='foo'] the closest thing you can do with a GPath is:
def xml = new XmlParser().parseText(text)
xml.'**'.div.findAll { it.#id=="foo" }
the '**' is pretty much the same as '//' in your XPath.
xml.'**'.div
will yield all the nodes of type div at any level.
Later filtering with findAll() with the given closure you get a list of nodes as you do in the XPath case
what you need is this:
def root = new XmlSlurper().parseText(<locOfXmlFileYouAreParsing>.toURL().text)
def foundNode = root.'**'.find{ it.#id == "foo" }
its the double * that will let you find it without knowing the path. At least this is how I do it.
Related
In Kotlin/Java, is there a standard function to determine if a String is a valid variable/function name without having to wrap it in back-ticks?
As in
functionIAmLookingFor("do-something") shouldBe false
functionIAmLookingFor("doSomething") shouldBe true
Edit: I do not want to enclose everything in backticks.
The reason why we need this: we have a tool that serializes instances into compilable Kotlin. And we have encountered the following edge case:
enum class AssetType { TRANSFERRABLE, `NON-TRANSFERRABLE` }
so as we reflect an instance with a field NON-TRANSFERRABLE, we need to wrap it in back-ticks:
val actual = MyAsset( type = `NON-TRANSFERRABLE`
This is why I'm asking this. Currently we are just saying in README that we do not support any names that require back-ticks at this time.
You could do it manually:
https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#isJavaIdentifierPart(char)
https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#isJavaIdentifierStart(char)
Something like this:
boolean isJavaIdentifier(String s) {
if (s == null || s.isEmpty()) return false;
if (!Character.isJavaIdentifierStart(s.charAt(0)) {
return false;
}
for (int i = 1, n = s.length(); i < n; ++i) {
if (!Character.isJavaIdentifierPart(s.charAt(i)) {
return false;
}
}
return true;
}
I don't know for Kotlin, but I don't think there is much difference using
770grappenmaker answer as reference.
I took a quick look at the kotlin compiler lexer. It has some predefined variables, here is an excerpt:
LETTER = [:letter:]|_
IDENTIFIER_PART=[:digit:]|{LETTER}
PLAIN_IDENTIFIER={LETTER} {IDENTIFIER_PART}*
ESCAPED_IDENTIFIER = `[^`\n]+`
IDENTIFIER = {PLAIN_IDENTIFIER}|{ESCAPED_IDENTIFIER}
FIELD_IDENTIFIER = \${IDENTIFIER}
Source: https://github.com/JetBrains/kotlin/blob/master/compiler/psi/src/org/jetbrains/kotlin/lexer/Kotlin.flex
These seem to be some kind of regexes, you could combine them to your needs and just match on them. As far as I can tell, this is how the compiler validates identifier names.
Edit: of course, this is code of the lexer, which means that if it finds any other token, it is invalid. All tokens and how to identify them are defined in that file and in the KtTokens file. You could use this information as a reference to find illegal tokens. For java, use the answer of NoDataFound.
I'm writing an XML serializer with JAXP. I'm receiving pseudo random data from a JAR and I'm building the DOM tree. I have to check if I already inserted the same Element into the tree; in order to perform this control I'm trying to use the method:
Element e = myDocument.getElementById(ao.getId());
if (e == null) {
// element is not a duplicate
access.appendChild(authorizationObject);
}else{
// element already in the tree
}
So, in every Element I create before adding them to the tree I set:
ao = a.getAuthorizationObject();
authorizationObject = myDocument.createElement("authorizationobject");
authorizationObject.setAttribute("id", ao.getId());
authorizationObject.setIdAttribute("id", true);
It can happen that in the object ao sometimes I get the same element twice (or more).
The problem is that the program always enter inside the if instruction.
You can find all the program's code here and the DTD here for your reference.
What am I doing wrong?
Thanks in advance for all your reply.
You have forgotten to append the authorizationObject to the access Element. Your code should be as follows
authorizationObject = myDocument.createElement("authorizationobject");
authorizationObject.setAttribute("id", ao.getId());
authorizationObject.setIdAttribute("id", true);
System.out.println("AO.ID = " + ao.getId());
access.appendChild(authorizationObject);
// then only this Element will be appended to the document
if (myDocument.getElementById(ao.getId()) == null ) {
I see that you have finally appended the authorization object to the document. but, it should be done prior to document.getElementById() method call
Hope this helps!
How can I use eval in groovy to evaluate the following String:
{key1=keyval, key2=[listitem1, listitem2], key3=keyval2}
All the list items and keyval is a String.
doing Eval.me("{key1=keyval, key2=[listitem1, listitem2], key3=keyval2}") is giving me the following error:
Ambiguous expression could be either a parameterless closure expression or an isolated open code block;
solution: Add an explicit closure parameter list, e.g. {it -> ...}, or force it to be treated as an open block by giving it a label, e.g. L:{...} at
I want to get HashMap
Is there no way you can get the data in JSON format? Then you could just use one of the parsers mentioned here.
You can parse that string by translating some of the characters, and writing your own binding to return variable names when Groovy tries to look them up, like so:
class Evaluator extends Binding {
def parse( s ) {
GroovyShell shell = new GroovyShell( this );
shell.evaluate( s )
}
Object getVariable( String name ) { name }
}
def inStr = '{key1=keyval, key2=[listitem1, listitem2], key3=keyval2}'
def inObj = new Evaluator().parse( inStr.tr( '{}=', '[]:' ) )
println inObj
But this is a very brittle solution, and getting the data in a friendlier format (as suggested by #Stefan) is definitely the best way to go...
I've got the following problem: I have a tree of objects of different classes where an action in the child class invalidates the parent. In imperative languages, it is trivial to do. For example, in Java:
public class A {
private List<B> m_children = new LinkedList<B>();
private boolean m_valid = true;
public void invalidate() {
m_valid = false;
}
public void addChild(B child) {
m_children.add(child);
child.m_parent = this;
}
}
public class B {
public A m_parent = null;
private int m_data = 0;
public void setData(int data) {
m_data = 0;
m_parent.invalidate();
}
}
public class Main {
public static void main(String[] args) {
A a = new A();
B b = new B();
b.setData(0); //invalidates A
}
}
How do I do the above in Haskell? I cannot wrap my mind around this, since once I construct an object in Haskell, it cannot be changed.
I would be much obliged if the relevant Haskell code is posted.
EDIT: the problem I am trying to solve is the following:
I have an application that edits documents. A document is a hierarchy of objects. When properties of children objects are modified, the document needs to be set to an invalid state, so as that the user knows that the document needs to be validated.
Modifying a tree which might require frequent excursions up the path to the root and back seems like the perfect job for a variant of the Zipper data structure with "scars", in the terminology of the original paper by Huet; the code samples from the paper also suggest a name of "memorising zipper". Of course, with some care, a regular zipper could also be used, but the augmented version might be more convenient and/or efficient to use.
The basic idea is the same as that behind a regular zipper, which already allows one to move up and down a tree in a purely functional manner (without any explicit back-pointers), but a "go up" operation followed by a "go down" operation becomes a no-op, leaving the focus at the original node (whereas with the regular zipper it would move it to the leftmost sibling of the original node).
Here's a link to the paper: GĂ©rard Huet, Functional Pearl: The Zipper. It's just six pages, but the ideas contained therein are of great usefulness to any functional programmer.
To answer the question in your title: Yes, you can create nodes which have links to their parents as well as their children. Example:
-- parent children
data Tree = Node (Maybe Tree) [Tree]
root = Node Nothing [a,b] -- I can "forward reference" a and b because haskell is lazy
a = Node (Just root) []
b = Node (Just root) []
The question is whether that's useful for your particular use-case (often times it isn't).
Now the question in your body: You're right, you can't change a value after it's been created. So once you have a valid tree, you'll always have a valid tree as long as the variable referencing that tree is in scope.
You didn't really describe what problem you're trying to solve, so I can't tell you how to functionally model what you're trying to do, but I'm sure there's a way without mutating the tree.
Here is some zipper code that demonstrates easy modification of the data a cursor points at as well as a "global" property of the tree. We build a tree, move the cursor to the node initially containing a 1, change it to a 3, and are left with a cursor pointing at that node in a fully updated tree.
import Data.Maybe (fromJust)
import Data.Tree
import Data.Tree.Zipper
type NodeData = Either Bool Int
type TreePath a = [TreePos Full a -> TreePos Full a]
firstChild' = fromJust . firstChild
parent' = fromJust . parent
prev' = fromJust . prev
next' = fromJust . next
-- Determine the path from the root of the tree to the cursor.
pathToMe :: TreePos Full NodeData -> TreePath NodeData
pathToMe t | isRoot t = []
| isFirst t = firstChild' : pathToMe (parent' t)
| otherwise = next' : pathToMe (prev' t)
-- Mark a tree as invalid, but leave the cursor in the same place.
invalidate :: TreePos Full NodeData -> TreePos Full NodeData
invalidate t = foldr ($) (setLabel (Left False) (root t)) (pathToMe t)
-- Set a node's internal data.
setData :: Int -> TreePos Full NodeData -> TreePos Full NodeData
setData = (invalidate . ) . setLabel . Right
main = let tree1 = Node (Left True) [Node (Right 1) [], Node (Right 2) []]
Just cursor = firstChild (fromTree tree1)
tree2 = setData 3 cursor
in do putStrLn (drawTree (fmap show tree1))
putStrLn (drawTree (fmap show (toTree tree2)))
putStrLn $ "Cursor at "++show (label tree2)
Output:
Left True
|
+- Right 1
|
`- Right 2
Left False
|
+- Right 3
|
`- Right 2
Cursor at Right 3
I don't have much experience with Haskell, but as far as I know it's not possible to have circles in the reference graph in pure functional languages. That means that:
You can't have a 2-way lists, children in trees pointing to their parents, etc.*
It is usually not enough to change just one node. Any node that is changed requires changes in every node starting from the "root" of the data structures all the way to the node you wish to change.
The bottom line is, I wouldn't try to take a Java (or any other imperative language) algorithm and try to convert it to Haskell. Instead, try to find a more functional algorithm (and maybe even a different data structure) to solve the problem.
EDIT:
From your clarification it's not entirely clear whether or not you need to invalidate only the direct parent of the object that changed or all its ancestors in the hierarchy, but that doesn't actually matter that much. Since invalidating an object basically means changing it and that's not possible, you basically have to create a modified duplicate of that object, and then you have to make its parent point to it to, so you have to create a new object for that as well. This goes on until you get to the root. If you have some recursion to traverse the tree in order to "modify" your object, then you can recreate the path from that object to the root on your way out of the recursion.
Hope that made sense. :s
*As pointed out in the comments by jberryman and in other answers, it is possible to create circular reference graphs in Haskell using lazy evaluation.
Look into using the Functor instance of the Maybe type.
For example, maybe your problem is something like this: you want to insert an element into a binary tree, but only if it isn't already present. You could do that with something like:
data Tree a = Node a (Tree a) (Tree a)
| Tip
maybeInsert :: a -> Tree a -> Maybe (Tree a)
maybeInsert a Tip = Just $ Node a Tip Tip
maybeInsert a (Node a' l r)
| a == a' = Nothing
| a < a' = fmap (\l'-> Node a' l' r) (maybeInsert a l)
| a > a' = fmap (\r'-> Node a' l r') (maybeInsert a r)
So the function will return Nothing if we found the element to be already present, or return Just the new tree with the element inserted.
Hopefully that is relevant to whatever you are trying to do.
Couldn't laziness take care of making sure validation doesn't happen too often? That way, you don't need to store the m_valid field.
For example, if you only validate on save, then you can edit the objects to your hearts content, without revalidating all the time; only when the user presses the 'Save' button is the value of validateDoc computed. Since I don't know for sure what your notion of valid means and what you need it for, I might be totally of the mark.
Untried & incomplete code:
data Document = Document { subDocs :: [SubDoc] }
data SubDoc = SubDoc { content :: String }
addSubDoc :: SubDoc -> (Document -> Document)
addSubDoc = error "not yet implemented: addSubDoc"
modifySubDoc :: Int -> (SubDoc -> SubDoc) -> (Document -> Document)
modifySubDoc = error "not yet implemented: modifySubDoc"
validateDoc :: Document -> Bool
validateDoc = all validateSubDoc . subDocs
validateSubDoc :: SubDoc -> Bool
validateSubDoc = not . null . contents
I'm assuming the overall validity of the document depends only on the subdocuments (simulated here by ensuring that they contain a non-empty string).
By the way, I think you forgot a a.addChild(b); in main.
Can anyone point me out, how can I parse/evaluate HQL and get map where key is table alias and value - full qualified class name.
E.g. for HQL
SELECT a.id from Foo a INNER JOIN a.test b
I wish to have pairs:
a, package1.Foo
b. package2.TestClassName
It's relatively easy to do for result set
HQLQueryPlan hqlPlan = ((SessionFactoryImpl)sf).getQueryPlanCache().getHQLQueryPlan( getQueryString(), false, ((SessionImpl)session).getEnabledFilters() );
String[] aliases = hqlPlan.getReturnMetadata().getReturnAliases();
Type[] types = hqlPlan.getReturnMetadata().getReturnTypes();
See details here.
Hardly a good way of doing it, but it seems you can get the AST through some internal interfaces and traverse this:
QueryTranslator[] translators = hqlPlan.getTranslators();
AST ast = (AST)((QueryTranslatorImpl)translators[0]).getSqlAST();
new NodeTraverser(new NodeTraverser.VisitationStrategy() {
public void visit(AST node) {
if(node.getType() == SqlTokenTypes.FROM_FRAGMENT || node.getType() == SqlTokenTypes.JOIN_FRAGMENT) {
FromElement id = (FromElement)node;
System.out.println(node+": "+id.getClassAlias()+" - "+id.getClassName());
}
}
}).traverseDepthFirst(ast);
So this seems to retrieve the alias-mappings from the compiled query, but I would be very careful using this solution: it typecasts objects to subclasses not usually visible to a hibernate-client and interprets the AST based on guessing the semantics of the different nodes. This might not work on all HQL-statements, and might not work, or have different behaviour, on a future hibernate-version.
I found right solution for my question. Your original post was almost correct except that part:
if(node.getType() == SqlTokenTypes.FROM_FRAGMENT || node.getType() == SqlTokenTypes.JOIN_FRAGMENT) {
FromElement id = (FromElement)node;
System.out.println(node+": "+id.getClassAlias()+" - "+id.getClassName());
}
Please correct your answer answer and I accept it.