【问题标题】:How to feed XML tag content modifications back to BeautifulSoup correctly?如何正确地将 XML 标签内容修改反馈给 BeautifulSoup?
【发布时间】:2021-02-05 00:11:11
【问题描述】:

我在使用 BeautifulSoup 编辑 XML 文件时遇到了一些问题。我在 stackoverflow 和其他地方发现了大量类似的主题,但没有一个解决这个特定的场景。我正在编辑本质上是一个列表的标签的内容。编辑部分效果很好,但是不知道如何正确的将修改后的内容发回给soup。

这是我目前所拥有的:

from bs4 import BeautifulSoup

XMLsource = """<?xml version="1.0" encoding="UTF-8" ?>
<root>
  <dataTag>
    <id>14</id>
    <players>var:val : var1:val1 : var2:val2 : testr:testl</players>
    <active>0</active>
  </dataTag>
  <dataTag>
    <id>15</id>
    <players>1var:1val : 1var1:1val1 : 1var2:1val2 : 1testr:1testl</players>
    <active></active>
  </dataTag>
  <dataTag>
    <id>16</id>
    <players>2var:2val : 2var1:2val1 : this_var:some_val : 2var2:2val2 : 2testr:2testl</players>
    <active>1</active>
  </dataTag>
  <dataTag>
    <id>17</id>
    <players>3var:3val : 3var1:3val1 : 3var2:3val2 : 3testr:3testl</players>
    <active>1</active>
  </dataTag>
</root>
"""

myarray = []
searchList = ['string', 'string_1', 'string_2', 'string_3', 'this_']
delimiter = " : "

def listToString(lst):
    return (delimiter.join(lst))

soup = BeautifulSoup(XMLsource, 'xml')

for a in soup.find_all('players'):
    for each in a:
        tagContents = a.string
        goodContents = list(tagContents.split(" : "))
        length = len(goodContents)
        for element in range(length):
            e = goodContents[element]
            if e != '':
                myarray.append(e)
        for stuff in searchList:
            for i, elem in enumerate(myarray):
                if stuff in elem:
                    myarray.remove(elem)
    a.string = listToString(myarray)

print(soup)

问题是a.string = listToString(myarray)。它只是在主for 循环中的每个循环中不断将myarray 添加到汤中。所以&lt;players&gt;标签的内容会堆积起来。你可以运行代码来看看我的意思。这是一个虚拟代码,它不会更改标签内容,因此更清楚问题所在。

现在已经三天测试和搜索 Internetz。我更改了代码一百万次,但我不是专业的程序员,所以我的代码通常是一个反复试验的过程,而这一次我只是无法破解它。谁能帮我修一下代码?

【问题讨论】:

  • 您的 xml 中没有 string(_n),请向我们展示预期结果
  • 嗨 uingtea,枚举听起来像是我需要解决的问题。我更新了代码以向您展示它的真正作用。它从任何&lt;players&gt; 标记中删除从searchList 获取的任何匹配字符串。这里的字符串是第三个&lt;players&gt; 标签中的'this_var:some_val'。前两个标签保持不变,字符串从第三个标签中删除。但在生成的 XML 中,只有第一个标签未被触及。所有后续标签都包含来自所有前面标签的字符串,因为不知道如何让 BeautifulSoup 将结果仅放在其原始标签中。这就是我需要解决的问题。

标签: python-3.x beautifulsoup xml-parsing


【解决方案1】:

所以在几个不眠之夜之后,我尝试了一种不同的方法,你瞧,它奏效了!所以这里是为了以防有人需要这样的脚本。那里可能仍然有一些多余的代码,但它做了它应该做的事情。它从任何已定义的 XML 标记中删除列表中定义的字符串,如果 XML 标记内容是列表,它也可以这样做。

from bs4 import BeautifulSoup

def listToString(lst):
    return (delimiter.join(lst))

XMLsource = """<?xml version="1.0" encoding="UTF-8" ?>
<root>
  <dataTag>
    <id>14</id>
    <players>var:val : var1:val1 : var2:val2 : testr:testl</players>
    <active>0</active>
  </dataTag>
  <dataTag>
    <id>15</id>
    <players>1var:1val : 1var1:1val1 : 1var2:1val2 : 1testr:1testl</players>
    <active></active>
  </dataTag>
  <dataTag>
    <id>16</id>
    <players>2var:2val : 2var1:2val1 : 2var2:2val2 : 2testr:2testl</players>
    <active>1</active>
  </dataTag>
  <dataTag>
    <id>17</id>
    <players>3var:3val : this_var:some_val : 3var1:3val1 : 3var2:3val2 : 3testr:3testl</players>
    <active>1</active>
  </dataTag>
</root>
"""

searchList = ['string', 'string_1', 'string_2', 'testr', 'this_v']

soup = BeautifulSoup(XMLsource, 'xml')
gamers = soup.find_all('players')
loopnum = len(gamers)
delimiter = " : "
newContents = []
badContents = []
goodContents = []
ii = 0

for xx in range(loopnum):
    newContents.clear()
    goodContents.clear()

    goodContents = gamers[xx].string
    goodContents = list(goodContents.split(" : "))

    for tagy in gamers[xx]:
        badContents.clear()

        for element in goodContents:
            e = element

            for stuff in searchList:
                if e != '':

                    if stuff in e:
                        badContents.append(e)

        newContents = [x for x in goodContents if x not in badContents]


    gamers[ii].string = listToString(newContents)
    ii += 1

print(soup)

【讨论】:

    猜你喜欢
    • 2014-08-03
    • 2018-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多