Remove null attributes and empty children from Node - groovy

I have a Node which I want to remove all null attributes and empty children from recursively before I write it to a file. What I have below works, but it seems like there should be a built in method for this. Have I missed something?
Node cleanNode(Node node) {
// Find null attributes
def attributesToRemove = []
for(e in node.attributes()) {
if(e.value == null) {
attributesToRemove.add(e.key)
}
}
// Remove null attributes
for(attribute in attributesToRemove) {
node.attributes().remove(attribute)
}
// Clean this node's children
for(child in node.children()) {
if(child instanceof Node) {
cleanNode(child)
}
}
// If node has no attributes, no children, and no text then discard it by setting it to null
if(!node.attributes() && !node.children() && !node.text()) {
node = null
}
node
}

There's not a build in method for doing this that I know of... You could get your code a little smaller (and recursively remove empty children) like so:
boolean cleanNode( Node node ) {
node.attributes().with { a ->
a.findAll { !it.value }.each { a.remove( it.key ) }
}
node.children().with { kids ->
kids.findAll { it instanceof Node ? !cleanNode( it ) : false }
.each { kids.remove( it ) }
}
node.attributes() || node.children() || node.text()
}
So given the xml:
def xml = '''<root>
| <head>
| <item>
| <woo/>
| </item>
| </head>
| <body att=''>
| <h1 name='' title='title'>
| woo
| </h1>
| </body>
| <tail>
| <item>hi</item>
| </tail>
|</root>'''.stripMargin()
We can parse it and clean it and print it out:
Node root = new XmlParser().parseText( xml )
cleanNode( root )
println XmlUtil.serialize( root )
which gives:
<?xml version="1.0" encoding="UTF-8"?><root>
<body>
<h1 title="title">woo</h1>
</body>
<tail>
<item>hi</item>
</tail>
</root>
As you can see, the whole <head> block has been cleaned as it contained no information.

If the xml contains namespaces the cleanNode method will result in namespace declarations sprayed onto every node.
To avoid this use new XmlParser(false, false), so the code becomes:
Node root = new XmlParser(false, false).parseText(xml)
cleanNode(root)
println XmlUtil.serialize(root)
This way the xml is nice and clean afterwards.
Many thanks to Tim for the original answer!

Related

keep response key nodejs sequelize on null with vue2

my response json
if null
dm_personal: null
if not null
if null
dm_personal: { id: 1 }
how to keep the key of response on null ?
or how to implement on vue2 if i fetch / load single data that set data() { return {} }
when its null it shown cannot read on null
here is my input
<vue-autosuggest
id="vi-dm_personal-penanggung_jawab"
v-model="form.transportir.dm_personal.full_name" // here is problem null
:suggestions=" [{ data: form.transportir.dm_personal.dm_personals }]" // here is problem null
...
in method or other we can use elvis operator like data?.data but in html element for v-model or any properties ( like :suggestions ) , how to best practice to clear the problem ???
Vue will only create the property if the parent object already exists but it will not create if the parent property value is null.
form: {
transportir: {
dm_personal: {}
}
}
So what you can do it convert the null into an object literal.
Live Demo :
new Vue({
el: '#app',
data: {
form: {
transportir: {
dm_personal: null
}
}
},
created() {
if (!this.form.transportir.dm_personal) {
this.form.transportir.dm_personal = {}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="text" v-model="form.transportir.dm_personal.full_name"/>
</div>

How to test a function is returning jsx in react-testing-library?

How can I test using jest/react-testing-library that a component is returning specific JSX?
I have toBeInstanceOf, etc, but it is hard to find information about "react-testing-library"
these are a few examples
const className = props.className;
if (!props.action) {
return props.children;
}
const { id, type, target } = props.action;
if (type === "EXTERNAL") {
return (
<a className={className} href={target}>
{props.children}
</a>
);
}
if (["page"].includes(type.toLowerCase())) {
return (
<Link className={className} key={id} to={"/" + target}>
{props.children}
</Link>
);
}
if (type.toLowerCase() === "play") {
return props.children;
} ...
as you can see every return is different jsx.
Ideally you should be looking for user-facing DOM elements, like text, labels, etc. However, for this sort of component, you may need to fall back to using test ids. You can add data-test-id="SomeComponent" to the various elements you're returning and then look for that using getByTestId (or queryByTestId, etc).

Loop through object with unkown levels of children in Preact

I'm trying to loop through an object with children, that can have children, that can have children.
Basically I won't know how many child elements and levels the object can contain. Is there an easy way to loop through these, and render out a component in a list view without having to call the Object.keys(myobject).map many times in side eachother. Inside the render function?
parent: {
term: "cats",
children: {
child: {
term: "kids",
otherdata: "dekme",
children: {
granddaughter: {term: "kids", otherdata: "dekme"},
grandson: {term: "mip", some other data: "si"}
}
},
}
}
And also the output should be something like:
<ul>
<li>
Parent
<ul>
<li>child</li>
<li>child
<ul>
<li>grandkid
</li>
</ul>
</li>
</ul>
</li>
</ul>
Great question! This class of problem is generally referred to as walking / tree walking, and there are probably some great libraries on npm that you could use to make it easier. We can write a simple recursive one by hand though. I'll assume your nested objects containing child elements look something like this:
var treeOfObjects = {
children: [
{
name: 'billy'
},
{
name: 'wanda',
children: [
{
name: 'stanley'
}
]
}
]
};
Here's a walk function that will crawl that tree, call an iterator function you supply on each child it finds, and collect up the results in an Array.
function walk(object, iterator, results) {
// no results array it means we're at the root.
// create the shared array, then map the root through our iterator.
if (!results) {
results = [iterator(object, null, object)];
}
if (object.children) {
for (let i=0; i<object.children.length; i++) {
// call the iterator on this child and append the result:
let value = object.children[i];
results.push(iterator(value, i, object));
// now "walk into" the child object (appending its children, etc):
walk(value, iterator, results);
}
}
return results;
}
Here's what it looks like in practice:
class Foo extends Component {
render({ someTreeOfObjects }) {
return (
<ul>
{walk(someTreeOfObjects, object => (
<li>{object.name}</li>
))}
</ul>
);
}
}
// render(<Foo someTreeOfObjects={treeOfObjects} />)
// .. produces:
// <ul>
// <li>billy</li>
// <li>wanda</li>
// <li>stanley</li>
// </ul>
Update - for nested output:
function nodeToListItem (object) {
// if we have children, we'll recurse into them
const children = object.children || [];
return (
<li>
{object.name}
{children.length>0 && (
<ul>
{children.map(nodeToListItem)}
<ul>
)}
</li>
);
}
class Foo extends Component {
render({ someTreeOfObjects }) {
return (
<ul>
{nodeToListItem(someTreeOfObjects)}
</ul>
);
}
}
Because the nesting from the original structure matches what we want to produce in the DOM, this ends up being a simple graph transformation.

How to 'import' a third party Javascript file into IntelliJ so that I can refer to it in a Typescript file

I am trying to write Typescript in IntelliJ and do not know how to tell IntelliJ to 'import' some third party Javascript files. IntelliJ (or is it Node.JS?) gives the following complaint:
C:/Temp/Typescript Example Project/ts/FinancialService.ts(2,17): error TS2095: Could not find symbol 'com'.
C:/Temp/Typescript Example Project/ts/FinancialService.ts(4,31): error TS2095: Could not find symbol 'com'.
I would like to 'import' Thirdparty.Calculator.js:
var com = com || {};
com.thirdparty = com.thirdparty || {};
com.thirdparty.Calculator = function() {
this.add = function(a, b) {
return a + b;
};
this.square = function(n) {
return n*n;
};
};
This is what FinancialService.ts looks like:
class FinancialService {
calculator: com.thirdparty.Calculator;
constructor() {
this.calculator = new com.thirdparty.Calculator();
}
calculateStuff(a: number) {
return this.calculator.square(a);
}
}
IntelliJ appears to transpile the Typescript as the following works and the correct values are logged to the console:
<html>
<head>
<script src="js/Thirdparty.Calculator.js"></script>
<script src="ts/FinancialService.js"></script>
<script>
var cal = new com.thirdparty.Calculator();
console.log("Calculator.square() is " + cal.square(9));
var fs = new FinancialService();
console.log("FinancialService.calculateStuff() is " + fs.calculateStuff(4));
</script>
</head>
<body>
</body>
</html>
How can I configure my project so that IntelliJ knows about Thirdparty.Calculator.js?
You could add Thirdparty.Calculator.d.ts to your project for TypeScript compilation purposes:
declare module com.thirdparty {
export class Calculator {
add(a: number, b: number) : number;
square(n: number) : number;
}
}
This would obviously need to grow with the third party library.
For very little extra effort, you could just convert it to TypeScript...
module com.thirdparty {
export class Calculator {
add = function(a: number, b: number) {
return a + b;
};
square(n: number) : number {
return n*n;
}
}
}

Groovy: Correct Syntax for XMLSlurper to find elements with a given attribute

Given a HTML file with the structure html -> body -> a bunch of divs what is the correct groovy statement to find all of the divs with a non blank tags attribute?
The following is not working:
def nodes = html.body.div.findAll { it.#tags != null }
because it finds all the nodes.
Try the following (Groovy 1.5.6):
def doc = """
<html>
<body>
<div tags="1">test1</div>
<div>test2</div>
<div tags="">test3</div>
<div tags="4">test4</div>
</body>
</html>
"""
def html = new XmlSlurper().parseText( doc)
html.body.div.findAll { it.#tags.text()}.each { div ->
println div.text()
}
This outputs:
test1
test4

Resources