Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如果具有相同的父元素,则合并具有相同标记的所有元素_Python_Xml_Python 3.x_Elementtree - Fatal编程技术网

Python 如果具有相同的父元素,则合并具有相同标记的所有元素

Python 如果具有相同的父元素,则合并具有相同标记的所有元素,python,xml,python-3.x,elementtree,Python,Xml,Python 3.x,Elementtree,我正在使用以下示例xml树: <group> <group_info> <Text> Text_1 </Text> </group_info> <group_info> <Text> Text_2 </Text> </group_info> <group_info>

我正在使用以下示例xml树:

<group>
   <group_info>
      <Text>
         Text_1
      </Text>
   </group_info>
   <group_info>
      <Text>
         Text_2
      </Text>
   </group_info>
   <group_info>
      <Text>
         Text_3
      </Text>
   </group_info>
</group>
我的想法是循环我的所有组,将
中的所有文本信息收集到一个字符串中,然后删除树中的所有这些元素,并用信息附加一个新元素。这可能不是最好的方法,但我相对来说是新的。但是,我的输出如下所示:

<group>
   <group_info>
      <Text>
         Text_1
      </Text>
   </group_info>
   <group_info>
      <Text>
         Text_2
      </Text>
   </group_info>
   <group_info>
      <Text>
         Text_3
      </Text>
   </group_info>
<group_info><Text>Text1 Text2 Text3</Text></group_info></group>

正文1
文本2
文本3
文本1文本2文本3

从技术上讲,最后一行是我需要的(虽然它看起来并不漂亮),但我不知道为什么它不删除其他不需要的
,即使我调用
elem.remove(child)

因为没有人出来回答,所以我花了一些时间,但是如果其他人遇到同样的问题,我有答案和建议

我从您在问题中看到的初始代码开始,它不会删除旧元素,并留下非常难看的最后一行

注意:
MY_XML=XML.etree.ElementTree.parse({PATH_OF_XML})

  • 如果您使用的是xml.etree.ElementTree,那么应该使用remove() 方法删除节点,但这要求您具有父节点 节点引用。我称之为elem.remove(child)[第9行]

  • 那么,为什么不删除它们呢?我发现修改 您正在迭代的对象会影响迭代。这不是 完全出乎意料的是,如果您在 迭代它。我找到了一种无法存储信息的方法 在一次迭代中删除元素

  • 我不得不把任务分成两部分:

    group_list = MY_XML.findall(".//group") # I do this because the actual xml is bigger with several groups
    text_list = [] 
    for group in group_list:
        string_text = ""
        for child in group :
            for super_child in child:
                if(super_child.text is not None): #Just in case None value because I cannot use string addition
                    string_text = string_text + super_child.text + " "
        text_list.append(string_text) #I stored all the info in 1 group as a value in this list because like I stated my overall xml might be bigger with more than 1 group
    
    for group in group_list:
        for elem in group.findall(".//group_info"):
            #loop over all possible <group> and removes all <group_info> inside
            group.remove(elem) 
    
    #And finally to append the information gathered:
    for group in group_list:
        Text_elem = ET.Element("Text")
        Text_elem.text = text_list[group_list.index(group)]
        group_info_elem = ET.Element("Kundenhinweis_redigiert")
        group_info_elem.append(Text_elem)
        group.append(Kund_elem)
    
    要调用该函数,请执行以下操作:

    root = MY_XML.getroot()
    pretty_xml = prettify(root)
    #Next line is optional, but sometimes your string contains empty lines or lines with white spaces and/or breaklines
    pretty_xml = "\n".join([s for s in pretty_xml.split("\n") if not s.isspace()])
    print(pretty_xml)
    
    输出将是:

    <group>
        <group_info>
            <Text>Text1 Text2 Text3</Text>
        </group_info>
    </group>
    
    
    文本1文本2文本3
    

    希望这能帮助其他新来者。

    因为没有人站出来回答,我花了一些时间,但如果其他人遇到同样的问题,我有答案和建议

    我从您在问题中看到的初始代码开始,它不会删除旧元素,并留下非常难看的最后一行

    注意:
    MY_XML=XML.etree.ElementTree.parse({PATH_OF_XML})

  • 如果您使用的是xml.etree.ElementTree,那么应该使用remove() 方法删除节点,但这要求您具有父节点 节点引用。我称之为elem.remove(child)[第9行]

  • 那么,为什么不删除它们呢?我发现修改 您正在迭代的对象会影响迭代。这不是 完全出乎意料的是,如果您在 迭代它。我找到了一种无法存储信息的方法 在一次迭代中删除元素

  • 我不得不把任务分成两部分:

    group_list = MY_XML.findall(".//group") # I do this because the actual xml is bigger with several groups
    text_list = [] 
    for group in group_list:
        string_text = ""
        for child in group :
            for super_child in child:
                if(super_child.text is not None): #Just in case None value because I cannot use string addition
                    string_text = string_text + super_child.text + " "
        text_list.append(string_text) #I stored all the info in 1 group as a value in this list because like I stated my overall xml might be bigger with more than 1 group
    
    for group in group_list:
        for elem in group.findall(".//group_info"):
            #loop over all possible <group> and removes all <group_info> inside
            group.remove(elem) 
    
    #And finally to append the information gathered:
    for group in group_list:
        Text_elem = ET.Element("Text")
        Text_elem.text = text_list[group_list.index(group)]
        group_info_elem = ET.Element("Kundenhinweis_redigiert")
        group_info_elem.append(Text_elem)
        group.append(Kund_elem)
    
    要调用该函数,请执行以下操作:

    root = MY_XML.getroot()
    pretty_xml = prettify(root)
    #Next line is optional, but sometimes your string contains empty lines or lines with white spaces and/or breaklines
    pretty_xml = "\n".join([s for s in pretty_xml.split("\n") if not s.isspace()])
    print(pretty_xml)
    
    输出将是:

    <group>
        <group_info>
            <Text>Text1 Text2 Text3</Text>
        </group_info>
    </group>
    
    
    文本1文本2文本3
    
    希望这对其他新手有所帮助。

    考虑一下,这是一种专门用于转换XML文件的专用语言,您可以通过索引相同的节点名称并对其文本值进行分组来运行。虽然Python的内置
    xml.ElementTree
    不支持XSLT,但其第三方模块
    lxml
    支持XSLT1.0脚本。您可以在不使用单个
    for
    循环或手动美化输出的情况下完成此操作

    XSLT(另存为.xsl文件,一个特殊的.xml文件)

    考虑一下,设计用于转换XML文件的专用语言,您可以通过索引相同的节点名称并将其文本值分组来运行。虽然Python的内置
    xml.ElementTree
    不支持XSLT,但其第三方模块
    lxml
    支持XSLT1.0脚本。您可以在不使用单个
    for
    循环或手动美化输出的情况下完成此操作

    XSLT(另存为.xsl文件,一个特殊的.xml文件)


    我在搜索中读到过,问题是我在公司的计算机上工作,不允许安装额外的python模块。我仅有的两个是
    xml.etree.ElementTree
    xml.dom.minidom
    导入“lxml”时,我得到了一个ImportError。哦,我多么希望。我无法控制xml输入,因为我从另一个部门接收xml输入,并且必须在python中执行更改。XSLT是一种行业语言,可以与或其他语言一起运行。请参阅安装程序,具体取决于您使用的是PC还是Unix,Python可以通过
    子流程在命令行中调用它。我将对此进行研究,一旦任务变得更困难,它可能会很有用。谢谢。我在搜索中读到过,问题是我在公司的计算机上工作,不允许安装额外的python模块。我仅有的两个是
    xml.etree.ElementTree
    xml.dom.minidom
    导入“lxml”时,我得到了一个ImportError。哦,我多么希望。我无法控制xml输入,因为我从另一个部门接收xml输入,并且必须在python中执行更改。XSLT是一种行业语言,可以与或其他语言一起运行。请参阅安装程序,具体取决于您使用的是PC还是Unix,Python可以通过
    子流程在命令行中调用它。我将对此进行研究,一旦任务变得更困难,它可能会很有用。非常感谢。
    
    <group>
        <group_info>
            <Text>Text1 Text2 Text3</Text>
        </group_info>
    </group>
    
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output indent="yes" method="xml"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:key name="group_key" match="group/*" use="name()" />
    
        <xsl:template match="/group">            
            <xsl:copy>
                <xsl:apply-templates select="*[generate-id() =
                                       generate-id(key('group_key', name())[1])]"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="group/*">
            <xsl:copy>
                <xsl:element name="{name(*)}">
                <xsl:for-each select="key('group_key', name())">
                    <xsl:value-of select="normalize-space(*)"/>
                    <xsl:if test="position() != last()">
                        <xsl:text> </xsl:text>
                    </xsl:if>
                </xsl:for-each>
                </xsl:element>
            </xsl:copy>
        </xsl:template>            
    </xsl:stylesheet>
    
    import lxml.etree as et
    
    # LOAD XML AND XSL
    doc = et.parse('/path/to/Input.xml')
    xsl = et.parse('/path/to/XSLT_Script.xsl')
    
    # CONFIGURE TRANSFORMER
    transform = et.XSLT(xsl)    
    
    # RUN TRANSFORMATION
    result = transform(doc)
    
    # PRINT RESULT
    print(result)  
    
    # SAVE TO FILE
    with open('/path/to/Output.xml', 'wb') as f:
       f.write(result)