diff --git a/src/main/java/org/apache/ibatis/parsing/XNode.java b/src/main/java/org/apache/ibatis/parsing/XNode.java index a7c9519454e..6d9a3f8aa5d 100644 --- a/src/main/java/org/apache/ibatis/parsing/XNode.java +++ b/src/main/java/org/apache/ibatis/parsing/XNode.java @@ -280,14 +280,11 @@ public Properties getChildrenAsProperties() { @Override public String toString() { - StringBuilder builder = new StringBuilder(); - toString(builder, 0); - return builder.toString(); + return buildToString(new StringBuilder(), 0).toString(); } - private void toString(StringBuilder builder, int level) { - builder.append("<"); - builder.append(name); + private StringBuilder buildToString(StringBuilder builder, int indentLevel) { + indent(builder, indentLevel).append("<").append(name); for (Map.Entry entry : attributes.entrySet()) { builder.append(" "); builder.append(entry.getKey()); @@ -295,34 +292,35 @@ private void toString(StringBuilder builder, int level) { builder.append(entry.getValue()); builder.append("\""); } - List children = getChildren(); - if (!children.isEmpty()) { + + NodeList nodeList = node.getChildNodes(); + if (nodeList == null || nodeList.getLength() == 0) { + builder.append(" />\n"); + } else { builder.append(">\n"); - for (XNode child : children) { - indent(builder, level + 1); - child.toString(builder, level + 1); + for (int i = 0, n = nodeList.getLength(); i < n; i++) { + Node node = nodeList.item(i); + short nodeType = node.getNodeType(); + if (nodeType == Node.ELEMENT_NODE) { + new XNode(xpathParser, node, variables).buildToString(builder, indentLevel + 1); + } else { + String text = getBodyData(node).trim(); + if (text.length() > 0) { + indent(builder, indentLevel + 1).append(text).append("\n"); + } + } } - indent(builder, level); - builder.append(""); - } else if (body != null) { - builder.append(">"); - builder.append(body); - builder.append(""); - } else { - builder.append("/>"); - indent(builder, level); + indent(builder, indentLevel).append("\n"); } - builder.append("\n"); + + return builder; } - private void indent(StringBuilder builder, int level) { + private StringBuilder indent(StringBuilder builder, int level) { for (int i = 0; i < level; i++) { - builder.append(" "); + builder.append(" "); } + return builder; } private Properties parseAttributes(Node n) { diff --git a/src/test/java/org/apache/ibatis/parsing/XNodeTest.java b/src/test/java/org/apache/ibatis/parsing/XNodeTest.java new file mode 100644 index 00000000000..ab0cc9d86fe --- /dev/null +++ b/src/test/java/org/apache/ibatis/parsing/XNodeTest.java @@ -0,0 +1,177 @@ +/* + * Copyright 2009-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ibatis.parsing; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Properties; + +import org.junit.jupiter.api.Test; + +class XNodeTest { + + @Test + void formatXNodeToString() { + XPathParser parser = new XPathParser( + "100Tom30BMWAudiBenz"); + String usersNodeToString = parser.evalNode("/users").toString(); + String userNodeToString = parser.evalNode("/users/user").toString(); + String carsNodeToString = parser.evalNode("/users/user/cars").toString(); + + // @formatter:off + String usersNodeToStringExpect = + "\n" + + " \n" + + " \n" + + " 100\n" + + " \n" + + " \n" + + " Tom\n" + + " \n" + + " \n" + + " 30\n" + + " \n" + + " \n" + + " \n" + + " BMW\n" + + " \n" + + " \n" + + " Audi\n" + + " \n" + + " \n" + + " Benz\n" + + " \n" + + " \n" + + " \n" + + "\n"; + // @formatter:on + + // @formatter:off + String userNodeToStringExpect = + "\n" + + " \n" + + " 100\n" + + " \n" + + " \n" + + " Tom\n" + + " \n" + + " \n" + + " 30\n" + + " \n" + + " \n" + + " \n" + + " BMW\n" + + " \n" + + " \n" + + " Audi\n" + + " \n" + + " \n" + + " Benz\n" + + " \n" + + " \n" + + "\n"; + // @formatter:on + + // @formatter:off + String carsNodeToStringExpect = + "\n" + + " \n" + + " BMW\n" + + " \n" + + " \n" + + " Audi\n" + + " \n" + + " \n" + + " Benz\n" + + " \n" + + "\n"; + // @formatter:on + + assertEquals(usersNodeToStringExpect, usersNodeToString); + assertEquals(userNodeToStringExpect, userNodeToString); + assertEquals(carsNodeToStringExpect, carsNodeToString); + } + + @Test + void xNodeToString() { + // @formatter:off + String xml = "\n" + + " \n" + + ""; + + String expected = "\n"; + // @formatter:on + + XPathParser parser = new XPathParser(xml); + XNode selectNode = parser.evalNode("/mapper/select"); + assertEquals(expected, selectNode.toString()); + } + + @Test + void testXnodeToStringVariables() throws Exception { + String src = "y = ${y}x = ${x}"; + String expected = "\n y = bar\n \n x = foo\n \n\n"; + Properties vars = new Properties(); + vars.put("x", "foo"); + vars.put("y", "bar"); + XPathParser parser = new XPathParser(src, false, vars); + XNode selectNode = parser.evalNode("/root"); + assertEquals(expected, selectNode.toString()); + } + +} diff --git a/src/test/java/org/apache/ibatis/parsing/XPathParserTest.java b/src/test/java/org/apache/ibatis/parsing/XPathParserTest.java index aee70307a2e..f82c912432f 100644 --- a/src/test/java/org/apache/ibatis/parsing/XPathParserTest.java +++ b/src/test/java/org/apache/ibatis/parsing/XPathParserTest.java @@ -204,63 +204,11 @@ private void testEvalMethod(XPathParser parser) { assertEquals((Float) 3.2f, parser.evalNode("/employee/active").getFloatAttribute("score")); assertEquals((Double) 3.2d, parser.evalNode("/employee/active").getDoubleAttribute("score")); - assertEquals("${id_var}", parser.evalNode("/employee/@id").toString().trim()); + assertEquals("\n ${id_var}\n", parser.evalNode("/employee/@id").toString().trim()); assertEquals(7, parser.evalNodes("/employee/*").size()); XNode node = parser.evalNode("/employee/height"); assertEquals("employee/height", node.getPath()); assertEquals("employee[${id_var}]_height", node.getValueBasedIdentifier()); } - @Test - void formatXNodeToString() { - XPathParser parser = new XPathParser( - "100Tom30BMWAudiBenz"); - String usersNodeToString = parser.evalNode("/users").toString(); - String userNodeToString = parser.evalNode("/users/user").toString(); - String carsNodeToString = parser.evalNode("/users/user/cars").toString(); - - // @formatter:off - String usersNodeToStringExpect = - "\n" - + " \n" - + " 100\n" - + " Tom\n" - + " 30\n" - + " \n" - + " BMW\n" - + " Audi\n" - + " Benz\n" - + " \n" - + " \n" - + "\n"; - // @formatter:on - - // @formatter:off - String userNodeToStringExpect = - "\n" - + " 100\n" - + " Tom\n" - + " 30\n" - + " \n" - + " BMW\n" - + " Audi\n" - + " Benz\n" - + " \n" - + "\n"; - // @formatter:on - - // @formatter:off - String carsNodeToStringExpect = - "\n" - + " BMW\n" - + " Audi\n" - + " Benz\n" - + "\n"; - // @formatter:on - - assertEquals(usersNodeToStringExpect, usersNodeToString); - assertEquals(userNodeToStringExpect, userNodeToString); - assertEquals(carsNodeToStringExpect, carsNodeToString); - } - }