首页 文章

需要帮助将子元素中的文本替换为XML中多个子元素的文本

提问于
浏览
1

我试图用树中其他子元素的文本替换XML树中的值文本 . 我是Python的新手需要一些帮助来解决这个问题 .

我的XML示例,其中省略了一些元素的长度:

<SalesOrder>
  <SalesOrderLines>
    <SalesOrderLine>
      <Item>
        <LineNo>1</LineNo>
        <Quantity>4.00</Quantity>
      </Item>
      <ConfigurationDetails>
         <ConfigurationDetail>
          <ConfigurationAttribute>
            <Name>ConfigurationModel</Name>
            <Value>HV</Value>
          </ConfigurationAttribute>
          <ConfigurationAttribute>
            <Name>EXWidth</Name>
            <Value>59.5</Value>
          </ConfigurationAttribute>
          <ConfigurationAttribute>
            <Name>EXHeight</Name>
            <Value>59.5</Value>
          </ConfigurationAttribute>
          <ConfigurationAttribute>
            <Name>Handing</Name>
            <Value>XO</Value>
          </ConfigurationAttribute>
          <ConfigurationAttribute>
            <Name>LongDescription</Name>
            <Value>This is a long paragraph of text i want to replace with 
            the above text for the Value sub-element</Value>
          </ConfigurationAttribute>
        </ConfigurationDetail>
      </ConfigurationDetails>
    </SalesOrderLine>
  </SalesOrderLines>
</SalesOrder>

这是我第一次尝试使用 ElementTree 库的Python代码:

import xml.etree.ElementTree as ET

from tkinter import Tk
from tkinter.filedialog import askopenfilename, asksaveasfilename

Tk().withdraw()
file = askopenfilename()

tree = ET.parse(file)
root = tree.getroot()

def model():
    for ConfigurationAttribute in root.iter('ConfigurationAttribute'):
        descrip = ConfigurationAttribute.find('Name').text
        model = ''

        if descrip == 'ConfigurationModel':
            model = ConfigurationAttribute.find('Value').text

def handing():
    for ConfigurationAttribute in root.iter('ConfigurationAttribute'):
        descrip = ConfigurationAttribute.find('Name').text
        handing = ''

        if descrip == 'Handing' and ConfigurationAttribute.find('Value') is 
not None:
            handing = ConfigurationAttribute.find('Value').text

def width():
    for ConfigurationAttribute in root.iter('ConfigurationAttribute'):
        descrip = ConfigurationAttribute.find('Name').text
        width = ''

        if descrip == 'EXWidth':
            width = ConfigurationAttribute.find('Value').text

def height():
    for ConfigurationAttribute in root.iter('ConfigurationAttribute'):
        descrip = ConfigurationAttribute.find('Name').text
        height = ''

         if descrip == 'EXHeight':
            height = ConfigurationAttribute.find('Value').text

for ConfigurationAttribute in root.iter('ConfigurationAttribute'):
    descrip = ConfigurationAttribute.find('Name').text

    if descrip == 'LongDescription':
        model()
        handing()
        width()
        height()        
        ConfigurationAttribute.find('Value').text = str(model), str(handing), 
            str(width), '" x ', str(height), '"' 

tree.write(asksaveasfilename(defaultextension='.xml',))

这会输出错误 . 我要看的是Value子元素中的文本段落将替换为ConfigurationModel,Handing,EXWidth和EXHeight Name子元素中的Value子元素文本,如下所示:

<ConfigurationAttribute>
    <Name>LongDescription</Name>
    <Value> HV, XO, 59.5" x 59.5"</Value>
</ConfigurationAttribute>

以下是运行代码时收到的错误:

回溯(最近一次调用最后一次):文件“\ app \ users \ Home \ natep \ Documents \ NP \ py \ PrestoParse.py”,第59行,在tree.write中(asksaveasfilename(defaultextension =' . xml',))文件“C:\ Users \ natep.RANDK \ AppData \ Local \ Programs \ Python \ Python37-32 \ lib \ xml \ etree \ ElementTree.py”,第777行,写入short_empty_elements = short_empty_elements)文件“C:\ Users \ natep .RANDK \ AppData \ Local \ Programs \ Python \ Python37-32 \ lib \ xml \ etree \ ElementTree.py“,第942行,在_serialize_xml中short_empty_elements = short_empty_elements)文件”C:\ Users \ natep.RANDK \ AppData \ Local \程序\ Python \ Python37-32 \ lib \ xml \ etree \ ElementTree.py“,第942行,在_serialize_xml中short_empty_elements = short_empty_elements)文件”C:\ Users \ natep.RANDK \ AppData \ Local \ Programs \ Python \ Python37-32 \ lib \ xml \ etree \ ElementTree.py“,第942行,在_serialize_xml中short_empty_elements = short_empty_elements)[上一行重复3次]文件”C:\ Users \ natep.RANDK \ AppData \ Local \ Programs \ Python \ Python37-在_serialize中的32 \ lib \ xml \ etree \ ElementTree.py“,第939行_xml write(_escape_cdata(text))TypeError:write()参数必须是str,而不是tuple

在输出文件中,我尝试更改的Value子元素为空,没有结束标记,现在删除了过去的所有内容 .

1 回答

  • 1

    考虑XSLT,这是专门用于转换XML文件的专用语言 . Python的第三方模块 lxml 可以运行XSLT 1.0脚本(不是内置的 etree )并且没有单个循环就可以运行 .

    具体来说,XSLT脚本运行Identity Transform以按原样复制整个文档 . 然后,脚本通过使用条件XPath(兄弟到XSLT)表达式提取前面的兄弟节点并最终将文本值与逗号分隔符和所需引号连接在一起来调整最后一个Value节点 .

    XSLT (另存为.xsl文件,下面将在Python中加载一个特殊的.xml文件)

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" indent="yes"/>
    
        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* | node()"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="ConfigurationAttribute[Name='LongDescription']">
            <xsl:copy>
                <xsl:apply-templates select="Name"/>
                <Value>
                    <xsl:value-of select="concat(preceding-sibling::ConfigurationAttribute[Name='ConfigurationModel']/Value, ', ',
                                                 preceding-sibling::ConfigurationAttribute[Name='Handing']/Value, ', ',
                                                 preceding-sibling::ConfigurationAttribute[Name='EXWidth']/Value, '&quot;', ' X ',
                                                 preceding-sibling::ConfigurationAttribute[Name='EXHeight']/Value, '&quot;')"/>
                </Value>
            </xsl:copy>
        </xsl:template>
    
    </xsl:stylesheet>
    

    XSLT Fiddle Demo

    Python

    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('output.xml', 'wb') as f:
       f.write(result)
    

相关问题