This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch GROOVY-11667 in repository https://gitbox.apache.org/repos/asf/groovy.git
commit ce20f1bdd5af922a34ae8afac4725bcbab5e629c Author: Eric Milles <[email protected]> AuthorDate: Fri May 16 16:07:31 2025 -0500 GROOVY-11667: `GPathResult`: overload `getAttribute` / `setAttribute` --- .../groovy/xml/slurpersupport/GPathResult.java | 13 ++++- .../test/groovy/groovy/xml/XmlSlurperTest.groovy | 66 +++++++++++++++++----- 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/subprojects/groovy-xml/src/main/java/groovy/xml/slurpersupport/GPathResult.java b/subprojects/groovy-xml/src/main/java/groovy/xml/slurpersupport/GPathResult.java index e654ebd1f7..5687294c94 100644 --- a/subprojects/groovy-xml/src/main/java/groovy/xml/slurpersupport/GPathResult.java +++ b/subprojects/groovy-xml/src/main/java/groovy/xml/slurpersupport/GPathResult.java @@ -88,18 +88,25 @@ public abstract class GPathResult extends GroovyObjectSupport implements Writabl */ @Override public void setMetaClass(final MetaClass metaClass) { - final MetaClass newMetaClass = new DelegatingMetaClass(metaClass) { + super.setMetaClass(new DelegatingMetaClass(metaClass) { @Override public Object getAttribute(final Object object, final String attribute) { return GPathResult.this.getProperty("@" + attribute); } + @Override + public Object getAttribute(final Class sender, final Object object, final String attribute, final boolean isSuper) { + return this.getAttribute(object, attribute); + } @Override public void setAttribute(final Object object, final String attribute, final Object newValue) { GPathResult.this.setProperty("@" + attribute, newValue); } - }; - super.setMetaClass(newMetaClass); + @Override + public void setAttribute(final Class sender, final Object object, final String attribute, final Object newValue, final boolean isSuper, final boolean isInner) { + this.setAttribute(object, attribute, newValue); + } + }); } /** diff --git a/subprojects/groovy-xml/src/test/groovy/groovy/xml/XmlSlurperTest.groovy b/subprojects/groovy-xml/src/test/groovy/groovy/xml/XmlSlurperTest.groovy index d38e4a63aa..63d4e13beb 100644 --- a/subprojects/groovy-xml/src/test/groovy/groovy/xml/XmlSlurperTest.groovy +++ b/subprojects/groovy-xml/src/test/groovy/groovy/xml/XmlSlurperTest.groovy @@ -18,14 +18,17 @@ */ package groovy.xml -import groovy.test.GroovyTestCase +import groovy.xml.slurpersupport.GPathResult +import org.junit.jupiter.api.Test import static groovy.xml.XmlUtil.serialize +import static org.junit.jupiter.api.Assertions.assertEquals -class XmlSlurperTest extends GroovyTestCase { +final class XmlSlurperTest { - def getRoot = { xml -> new XmlSlurper().parseText(xml) } + final Closure<GPathResult> getRoot = { String xml -> new XmlSlurper().parseText(xml) } + @Test void testWsdl() { def wsdl = ''' <definitions name="AgencyManagementService" @@ -54,6 +57,7 @@ class XmlSlurperTest extends GroovyTestCase { xml.message.findAll { true }.each { assert it.name() == "message"} } + @Test void testElement() { // can't update value directly with XmlSlurper, use replaceNode instead // GpathSyntaxTestSupport.checkUpdateElementValue(getRoot) @@ -65,39 +69,68 @@ class XmlSlurperTest extends GroovyTestCase { GpathSyntaxTestSupport.checkCDataText(getRoot) } + @Test void testAttribute() { GpathSyntaxTestSupport.checkAttribute(getRoot) GpathSyntaxTestSupport.checkAttributes(getRoot) GpathSyntaxTestSupport.checkAttributeTruth(getRoot) } + // GROOVY-11667 + @Test + void testAttribute2() { + def xml = ''' + <person> + <name>John Doe</name> + </person> + ''' + def path = getRoot(xml) + def text = [email protected]() ?: null + + assert text == null + assert new Inner(path).@id == null + } + + static class Inner { + protected id + Inner(GPathResult gpath) { + this.@id = [email protected]() ?: null + } + } + + @Test void testNavigation() { GpathSyntaxTestSupport.checkChildren(getRoot) GpathSyntaxTestSupport.checkParent(getRoot) GpathSyntaxTestSupport.checkNestedSizeExpressions(getRoot) } + @Test void testTraversal() { TraversalTestSupport.checkDepthFirst(getRoot) TraversalTestSupport.checkBreadthFirst(getRoot) } + @Test void testIndices() { GpathSyntaxTestSupport.checkNegativeIndices(getRoot) GpathSyntaxTestSupport.checkRangeIndex(getRoot) } + @Test void testReplacementsAndAdditions() { GpathSyntaxTestSupport.checkReplaceNode(getRoot) GpathSyntaxTestSupport.checkReplaceMultipleNodes(getRoot) GpathSyntaxTestSupport.checkPlus(getRoot) } + @Test void testMixedMarkup() { MixedMarkupTestSupport.checkMixedMarkup(getRoot) MixedMarkupTestSupport.checkMixedMarkupText(getRoot) } + @Test void testReplace() { def input = "<doc><sec>Hello<p>World</p></sec></doc>" def replaceSlurper = new XmlSlurper().parseText(input) @@ -109,6 +142,7 @@ class XmlSlurperTest extends GroovyTestCase { assert output == "<doc><t>Hello<p>World</p></t></doc>" } + @Test void testNamespacedName() { def wsdl = ''' <definitions name="AgencyManagementService" @@ -130,6 +164,7 @@ class XmlSlurperTest extends GroovyTestCase { } // GROOVY-4637 + @Test void testNamespacedAttributes() { def xml = """ <RootElement xmlns="http://www.ivan.com/ns1" xmlns:two="http://www.ivan.com/ns2"> @@ -144,6 +179,7 @@ class XmlSlurperTest extends GroovyTestCase { } // GROOVY-6255 + @Test void testXmlNamespacedAttributes() { def xml = ''' <appendix version="5.0" xmlns="http://docbook.org/ns/docbook" xmlns:xml="http://www.w3.org/XML/1998/namespace"> @@ -157,6 +193,7 @@ class XmlSlurperTest extends GroovyTestCase { } // GROOVY-6356 + @Test void testSetAndRemoveAttributesWithNamespace() { def xmlSource = '''<bob:root xmlns:bob="stuff" @@ -179,6 +216,7 @@ class XmlSlurperTest extends GroovyTestCase { } // GROOVY-6356 + @Test void testSetAndRemoveAttributesNamespaceUnaware() { def xmlSource = '''<bob:root xmlns:bob="stuff" @@ -198,11 +236,13 @@ class XmlSlurperTest extends GroovyTestCase { } // GROOVY-5931 + @Test void testIterableGPathResult() { - def xml = """ - <RootElement> - <ChildElement ItemId="FirstItemId">Child element data</ChildElement> - </RootElement>""" + def xml = ''' + <RootElement> + <ChildElement ItemId="FirstItemId">Child element data</ChildElement> + </RootElement> + ''' def root = new XmlSlurper().parseText(xml) @@ -215,11 +255,12 @@ class XmlSlurperTest extends GroovyTestCase { } // GROOVY-7781 + @Test void testNamespacedAttributesAccessedWithDifferentPrefix() { def xml = ''' - <x:root xmlns:x="blah"> - <x:child x:id="1">c</x:child> - </x:root> + <x:root xmlns:x="blah"> + <x:child x:id="1">c</x:child> + </x:root> ''' def root = new XmlSlurper(false, true).parseText(xml).declareNamespace(t: 'blah') @@ -227,9 +268,9 @@ class XmlSlurperTest extends GroovyTestCase { assert root.'t:child'.@'t:id' == '1' } + @Test void testParsePath() { - - def file = File.createTempFile('test','xml') + File file = File.createTempFile('test','xml') file.deleteOnExit() file.text = ''' <definitions name="AgencyManagementService" @@ -257,6 +298,5 @@ class XmlSlurperTest extends GroovyTestCase { assert xml.message.part.lookupNamespace("") == "http://schemas.xmlsoap.org/wsdl/" assert xml.message.part.lookupNamespace("undefinedPrefix") == null xml.message.findAll { true }.each { assert it.name() == "message"} - } }
