Lookahead в groovy при разборе xml?

Я пытаюсь разобрать xml-дерево. Я бы хотел:

  • Выведите представление пути к каждому элементу. Есть ли более разумный способ создать путь?
  • Выведите имя и значение узлов с primaryType="content" (узлы содержимого)
  • Found a smarter/better approach. Filters? Smarter closures?
    • Can I do it another way to lookahead
  • Этот пример является простым примером более сложного случая из реальной жизни, который у меня есть. Поиск элементов-свойств с primaryType="text"

При запуске кода ниже я получаю:

root/
--folder1/
----folder2/
metadataitem: <- "Wrong" = not what I want
found value: findme

Но я хочу:

root/
--folder1/
----folder2/
------item: <- Without "metadata"  
found value: findme
  • Было бы легко заменить строку на «метаданные» -> «», но это не очень хорошее решение.
  • Я также хотел бы более разумное решение, если у вас есть время.

Заранее спасибо!

Пример:

def example = '''
<node name="root">
    <property name="primaryType">
        <value>folder</value>
    </property>
    <node name="metadata">
        <property name="primaryType">
            <value>metadata</value>
        </property>
        <property name="other">
            <value>...</value>
        </property>
    </node>
    <node name="folder1">
        <property name="primaryType">
            <value>folder</value>
        </property>
        <node name="metadata">
            <property name="primaryType">
                <value>metadata</value>
            </property>
            <property name="other">
                <value>...</value>
            </property>
        </node>
        <node name="folder2">
            <property name="primaryType">
                <value>folder</value>
            </property>
            <property name="other">
                <value>...</value>
            </property>
            <node name="metadata">
                <property name="primaryType">
                    <value>metadata</value>
                </property>
                <property name="other">
                    <value>...</value>
                </property>
            </node>
            <node name="item">
                <property name="primaryType">
                    <value>content</value>
                </property>
                <property name="text">
                    <value>findme</value>
                </property>
                <property name="other">
                    <value>...</value>
                </property>
            </node>
        </node>
    </node>
</node>
'''

def xml = new XmlSlurper().parseText(example);

def listContent(node,pad) {
    node.node.property.find { it.@name == "primaryType" && it.text() == "content" }.each { 
        it.parent().property.each { property ->
            if(property.@name == "text") {
                println "" + property.parent().@name + ":"// Want: "item". Gets: "metadataitem" due to parent()
                println "found value: " + property.text()
            }
        }
    }
}

def listFolders(node,pad) {
    node.property.find { it.text() == "folder" }.each { property ->
        println "-".multiply(pad) + property.parent().@name + "/"
        listContent(property.parent(),pad) 
    }
    node.children().each { child ->
        listFolders(child, pad+2)
    }
}
listFolders(xml,0)

person C-B    schedule 25.11.2013    source источник


Ответы (1)


Предоставленный вами код (здесь немного изменен)

def listContent( node, pad = 0 ) {
    node.node.property.find { it.@name == "primaryType" && it.text() == "content" }.each { 
        it.parent().property.each { property ->
            if(property.@name == "text") {
                println  "${'-'*pad}${property.parent().@name}:"
                println "found value: " + property.text()
            }
        }
    }
}

def listFolders( node, pad = 0 ) {
    node.property.find { it.text() == "folder" }.each { property ->
        println "${'-'*pad}${property.parent().@name}/"
        listContent(property.parent(),pad + 2) 
    }
    node.children().each { child ->
        listFolders(child, pad+2)
    }
}
listFolders( xml )

Кажется, делает то, что вы хотите, и печатает

root/
--folder1/
----folder2/
------item:
found value: findme

Я не понимаю, чем это отличается от требования в вопросе?

person tim_yates    schedule 26.11.2013
comment
Спасибо за отзыв. Я знал о значениях по умолчанию раньше - хорошо. К сожалению, я не получаю такого же результата (ни для моей, ни для вашей версии). Я получаю: ... ------metadataitem: ... Не ------item: Я уверен, что это ошибка ОС (поскольку вы говорите, что получаете элемент вместо элемента метаданных, как я получаю). Я использую Groovy Версия: 2.1.0 JVM: 1.7.0_17 Поставщик: Oracle Corporation ОС: Mac OS X - person C-B; 27.11.2013
comment
Если я скажу так: XML представляет собой древовидную структуру файлов, где файлы — это все объекты-узлы с primaryType=content. Теперь я хочу пройти всю XML-структуру, чтобы иметь возможность сериализовать контент/элементы как настоящие файлы в соответствии со структурой папок, определенной XML. Это также дает мне другие преимущества (есть варианты использования, когда я хочу найти только специальный элемент, например, с заданным путем к папке, или дать мне этот путь для элемента с именем x). - person C-B; 27.11.2013