Точное совпадение подстроки в строке Python - PullRequest
0 голосов
/ 31 марта 2020

Я знаю, что этот вопрос довольно часто встречается, но мой пример ниже немного сложнее, чем предполагает заголовок вопроса.

Предположим, у меня есть следующий файл "test. xml":

<?xml version="1.0" encoding="UTF-8"?>
<test:xml xmlns:test="http://com/whatever/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <parent xsi:type="parentType">
    <child xsi:type="childtype">
      <grandchild>
        <greatgrandchildone>greatgrandchildone</greatgrandchildone>
        <greatgrandchildtwo>greatgrandchildtwo</greatgrandchildtwo>
      </grandchild><!--random comment -->
    </child>
    <child xsi:type="childtype">
      <greatgrandchildthree>greatgrandchildthree</greatgrandchildthree>
      <greatgrandchildfour>greatgrandchildfour</greatgrandchildfour><!--another random comment -->
    </child>
    <child xsi:type="childtype">
      <greatgrandchildthree>greatgrandchildthree</greatgrandchildthree>
      <greatgrandchildfour>greatgrandchildfour</greatgrandchildfour><!--third random comment -->
    </child>
  </parent>
</test:xml>

В моей программе ниже я делаю две основные вещи:

  1. Поиск всех узлов в xml, которые содержат атрибут "type"
  2. L oop через каждый узел xml и выясните, является ли он дочерним по отношению к элементу, который содержит атрибут "type"

Это мой код:

from lxml import etree
import re

xmlDoc = etree.parse("test.xml")
root = xmlDoc.getroot()

nsmap = {
    'xsi': 'http://www.w3.org/2001/XMLSchema-instance'
}

nodesWithType = []

def check_type_in_path(nodesWithType, path, root):
    typesInPath = []
    elementType = ""

    for node in nodesWithType:
        print("checking node: ", node, " and path: ", path)

        if re.search(r"\b{}\b".format(
            node), path, re.IGNORECASE) is not None:

            element = root.find('.//{0}'.format(node))
            elementType = element.attrib.get(f"{{{nsmap['xsi']}}}type")
            if elementType is not None:
                print("found an element for this path. adding to list")
                typesInPath.append(elementType)
        else:
            print("element: ", node, " not found in path: ", path)

    print("path ", path ," has types: ", elementType)
    print("-------------------")
    return typesInPath

def get_all_node_types(xmlDoc):
    nodesWithType = []
    root = xmlDoc.getroot()

    for node in xmlDoc.iter():

        path = "/".join(xmlDoc.getpath(node).strip("/").split('/')[1:])

        if "COMMENT" not in path.upper():
            element = root.find('.//{0}'.format(path))
            elementType = element.attrib.get(f"{{{nsmap['xsi']}}}type")
            if elementType is not None:
                nodesWithType.append(path)

    return nodesWithType

nodesWithType = get_all_node_types(xmlDoc)
print("nodesWithType: ", nodesWithType)

for node in xmlDoc.xpath('//*'):
    path = "/".join(xmlDoc.getpath(node).strip("/").split('/')[1:])
    typesInPath = check_type_in_path(nodesWithType, path, root)

Код должен возвращать все типы, содержащиеся в определенном пути. Например, рассмотрим путь parent/child[3]/greatgrandchildfour. Этот путь является дочерним (прямым или удаленным) двух узлов, которые содержат атрибут «тип»: parent и parent/child[3]. Поэтому я ожидал бы, что массив nodesWithType для этого конкретного узла будет включать в себя как parentType, так и childtype.

Однако, исходя из приведенных ниже отпечатков, массив nodesWithType для этого узла включает только тип «parentType» и не включает «childtype». Основное внимание в этом логе c уделяется проверке, включен ли путь к узлу с типом в путь к рассматриваемому узлу (следовательно, проверка на точное совпадение строки). Но это явно не работает. Я не уверен, что это потому, что внутри условия есть аннотации массива, которые его не проверяют, или, может быть, что-то еще.

Для приведенного выше примера возвращаемое значение:

checking node:  parent  and path:  parent/child[3]/greatgrandchildfour
found an element for this path. adding to list
checking node:  parent/child[1]  and path:  parent/child[3]/greatgrandchildfour
element:  parent/child[1]  not found in path:  parent/child[3]/greatgrandchildfour
checking node:  parent/child[2]  and path:  parent/child[3]/greatgrandchildfour
element:  parent/child[2]  not found in path:  parent/child[3]/greatgrandchildfour
checking node:  parent/child[3]  and path:  parent/child[3]/greatgrandchildfour
element:  parent/child[3]  not found in path:  parent/child[3]/greatgrandchildfour
path  parent/child[3]/greatgrandchildfour  has types:  parentType
...