How I Built a Groovy Script to Parse Zookeeper XML Configs for MySQL
After completing a DOM‑based XML parsing class, I tackled the messy Zookeeper configuration hierarchy for MySQL services, exposing unexpected node structures, missing values, and hundreds of database settings, and finally crafted a Groovy script that traverses the XML, filters relevant keys, and logs the extracted configuration details.
Yesterday I finished a DOM‑based XML parsing class and immediately put it to work on the Zookeeper configuration used by many services, only to discover a large number of hidden pitfalls.
The configuration hierarchy follows a root node, then service nodes, each containing version nodes, followed by change and unchange nodes. Under these, every child is a zknode element, and many entries lack a value attribute, making extraction non‑trivial.
Below are screenshots of the Zookeeper configuration tree:
Extracted XML fragments reveal dozens of zknode entries such as datadb.username, db.host.r, DB_CONNECTION, and many MySQL‑related keys. The author notes that the file contains over a hundred different database configuration items.
After repeated attempts, a Groovy script was created to automate the extraction:
package com.fun.ztest.groovy
import com.fun.frame.httpclient.FanLibrary
import com.fun.utils.XMLUtil
import org.slf4j.Logger
import org.slf4j.LoggerFactory
class Td extends FanLibrary {
private static Logger logger = LoggerFactory.getLogger(Td.class)
public static void main(String[] args) {
def xml = XMLUtil.parseXml("/Users/fv/Downloads/d.xml", "root")
xml.get(0).getChildren().each {
logger.error("服务名:{}", it.getAttrs().get(0).getValue())
def children = it.getChildren()
children.each { child ->
def attr1 = child.getAttrs()
def name = attr1.get(0).getValue()
if (name ==~ /[vV]\d.\d+/) {
logger.error("zk版本:${name}")
def children1 = child.getChildren()
children1.each { sub ->
def children2 = sub.getChildren()
children2.each { leaf ->
def attrs = leaf.getAttrs()
if (attrs.size() > 1) {
def var = attrs.get(0).getValue()
def value = attrs.get(1).getValue()
if (!(value ==~ /\d+/)) {
if (var.contains("druid") || var.contains("db") || var.contains("user") ||
value.contains("mysql") || value.contains("neworiental")) {
if (!value.contains("{") && !value.contains(".txt") &&
!var.contains("service") && !var.contains("maill") &&
!var.contains("host") && !var.contains("driver") &&
!var.contains("filters") && !var.contains("center") &&
!var.contains("rabbit") && !var.contains("order") &&
!value.contains("http")) {
logger.info("key: {},value: {}", var, value)
}
}
}
}
}
}
}
}
}
testOver()
}
}The script loads the XML file, iterates through each service version, and then walks the nested zknode elements. It filters keys that contain keywords like “druid”, “db”, or “user” while excluding entries that appear to be placeholders, file references, or unrelated configuration items. Matching key‑value pairs are logged for further processing.
In the end, the author acknowledges the frustration of dealing with such a chaotic configuration but confirms that the script resolves the problem, humorously noting the need for a widescreen monitor to handle the output.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
