Рекурсивно включить дочерние узлы XML Groovy - PullRequest
0 голосов
/ 21 мая 2018

У меня есть следующий XML-файл:

<testItems>
<children>
<testItem name=TestSuite1 enabled=false>
    <children>
        <testItem name=test1 enabled=false>
        </testItem>
        <testItem name=test2 enabled=false>
        </testItem>
        <testItem name=test3 enabled=false>
        </testItem>
    </children>
</testItem>
<testItem name=TestSuite2 enabled=false>
    <children>
        <testItem name=test3 enabled=false>
        </testItem>
        <testItem name=test4 enabled=false>
        </testItem>
        <testItem name=test5 enabled=false>
        </testItem>
    </children>
</testItem>

Структура может измениться (это означает, что глубина дерева может измениться).

Я хочу включитьTestSuite1 и тем самым рекурсивно включите всех потомков TestSuite1 (test1, test2, test3)

Пока у меня есть:

def root = new XmlParser(false, false, true).parse(mdsFile)

 root.depthFirst().each {
                if (it.@name == testItemToEnable) {
                    it.@enabled = true
                    it.children.depthFirst().each { child ->
                    child.@enabled = true
                }
            }

, но у меня есть следующее исключение:

 No signature of method: groovy.util.NodeList.depthFirst() is applicable for argument types: () values: []

[ДОБАВЛЕНО ПОСЛЕ ВОПРОСА В КОММЕНТАРИЯХ]

<testItems>
<children>
<testItem name="TestSuite1" enabled="false">
  <children>
    <testItem name="test1" enabled="false">
    </testItem>
    <testItem name="test2" enabled="false">
    <children>
        <testItem name="testX" enabled="false">
    </testItem>
    </children>
    </testItem>
    <testItem name="test3" enabled="false">
    </testItem>
  </children>
</testItem>
<testItem name="TestSuite2" enabled="false">
  <children>
    <testItem name="test3" enabled="false">
    </testItem>
    <testItem name="test4" enabled="false">
    </testItem>
    <testItem name="test5" enabled="false">
    </testItem>
  </children>
</testItem>

Сценарий: 1. suiteToEnable = 'test1' => test1, TestSuite1 становятся истинными

suiteToEnable = 'testX' => testX, test2 и TestSuite1 становятся истинными

1 Ответ

0 голосов
/ 21 мая 2018

[Изменено после уточняющего комментария]

Следующий код устанавливает для разрешенных атрибутов значение true и выводит полученную строку:

import groovy.xml.*

def str = '''\
<testItems>
  <children>
    <testItem name="TestSuite1" enabled="false">
      <children>
        <testItem name="test1" enabled="false">
        </testItem>
        <testItem name="test2" enabled="false">
        </testItem>
        <testItem name="test3" enabled="false">
        </testItem>
      </children>
    </testItem>
    <testItem name="TestSuite2" enabled="false">
      <children>
        <testItem name="test3" enabled="false">
        </testItem>
        <testItem name="test4" enabled="false">
        </testItem>
        <testItem name="test5" enabled="false">
        </testItem>
      </children>
    </testItem>
  </children>
</testItems>'''

def xml = new XmlSlurper().parseText(str)

def suiteToEnable = 'TestSuite2'

xml.'**'.find { 
  it.name() == 'testItem' && it.@name == suiteToEnable
}.'**'.findAll { 
  it.name() == 'testItem'
}*.@enabled = 'true'

println XmlUtil.serialize(xml)

output:

<?xml version="1.0" encoding="UTF-8"?><testItems>
  <children>
    <testItem name="TestSuite1" enabled="false">
      <children>
        <testItem name="test1" enabled="false"/>
        <testItem name="test2" enabled="false"/>
        <testItem name="test3" enabled="false"/>
      </children>
    </testItem>
    <testItem name="TestSuite2" enabled="true">
      <children>
        <testItem name="test3" enabled="true"/>
        <testItem name="test4" enabled="true"/>
        <testItem name="test5" enabled="true"/>
      </children>
    </testItem>
  </children>
</testItems>

при этом используется псевдоним deepFirst ** и оператор распространения *..

[добавление после вопроса в комментарии]

дляВаш второй вопрос о включении только одного ребенка и его прародителя мы можем сделать:

def xml = new XmlSlurper().parseText(str)

def suiteToEnable = 'test2'

def item = xml.'**'.find { 
  it.name() == 'testItem' && it.@name == suiteToEnable
}
item.@enabled = 'true'
item.parent().parent().@enabled = 'true'

println XmlUtil.serialize(xml)

, который печатает:

<?xml version="1.0" encoding="UTF-8"?><testItems>
  <children>
    <testItem name="TestSuite1" enabled="true">
      <children>
        <testItem name="test1" enabled="false"/>
        <testItem name="test2" enabled="true"/>
        <testItem name="test3" enabled="false"/>
      </children>
    </testItem>
    <testItem name="TestSuite2" enabled="false">
      <children>
        <testItem name="test3" enabled="false"/>
        <testItem name="test4" enabled="false"/>
        <testItem name="test5" enabled="false"/>
      </children>
    </testItem>
  </children>
</testItems>

[приложение 2 после другого вопроса в комментариях]

следующий код сначала находит определенный узел, а затем устанавливает все родительские узлы с именем элемента testItem в enabled="true":

def xml = new XmlSlurper().parseText(str)
def suiteToEnable = 'testX'

// first find our target node
def item = xml.'**'.find { 
  it.name() == 'testItem' && it.@name == suiteToEnable
}

// then get the parents recursively, find all parents called
// 'testItem' and set them to enabled = 'true'
getParents(item).findAll { it.name() == 'testItem' }.each { 
  it.@enabled = 'true' 
}

println XmlUtil.serialize(xml)

// recursively get parents of node using the '..' alias for 
// the node.parent() call
def getParents(node) {
  (node.is(node.'..') ? [] : getParents(node.'..')) + [node]
}

выводит на печать:

<testItems>
  <children>
    <testItem name="TestSuite1" enabled="true">
      <children>
        <testItem name="test1" enabled="false"/>
        <testItem name="test2" enabled="true">
          <children>
            <testItem name="testX" enabled="true"/>
          </children>
        </testItem>
        <testItem name="test3" enabled="false"/>
      </children>
    </testItem>
    <testItem name="TestSuite2" enabled="false">
      <children>
        <testItem name="test3" enabled="false"/>
        <testItem name="test4" enabled="false"/>
        <testItem name="test5" enabled="false"/>
      </children>
    </testItem>
  </children>
</testItems>
...