Node.toprettyxml () добавляет новые строки в DOCTYPE в Python

При использовании prettify мой DOCTYPE разбивается на три строки. Как я могу держать его на одной строке?

«Неработающий» вывод:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE smil
  PUBLIC '-//W3C//DTD SMIL 2.0//EN'
  'http://www.w3.org/2001/SMIL20/SMIL20.dtd'>
<smil xmlns="http://www.w3.org/2001/SMIL20/Language">
  <head>
    <meta base="rtmp://cp23636.edgefcs.net/ondemand"/>
  </head>
  <body>
    <switch>
      <video src="mp4:soundcheck/1/clay_aiken/02_sc_ca_sorry_256.mp4" system-bitrate="336000"/>
      <video src="mp4:soundcheck/1/clay_aiken/02_sc_ca_sorry_512.mp4" system-bitrate="592000"/>
      <video src="mp4:soundcheck/1/clay_aiken/02_sc_ca_sorry_768.mp4" system-bitrate="848000"/>
      <video src="mp4:soundcheck/1/clay_aiken/02_sc_ca_sorry_1128.mp4" system-bitrate="1208000"/>
    </switch>
  </body>
</smil>

Сценарий:

 import csv
import sys
import os.path

from xml.etree import ElementTree
from xml.etree.ElementTree import Element, SubElement, Comment, tostring

from xml.dom import minidom

def prettify(doctype, elem):
    """Return a pretty-printed XML string for the Element.
    """
    rough_string = doctype + ElementTree.tostring(elem, 'utf-8')
    reparsed = minidom.parseString(rough_string)
    return reparsed.toprettyxml(indent="  ", encoding = 'utf-8')

doctype = '<!DOCTYPE smil PUBLIC "-//W3C//DTD SMIL 2.0//EN" "http://www.w3.org/2001/SMIL20/SMIL20.dtd">'

video_data = ((256, 336000),
              (512, 592000),
              (768, 848000),
              (1128, 1208000))


with open(sys.argv[1], 'rU') as f:
    reader = csv.DictReader(f)
    for row in reader:
        root = Element('smil')
        root.set('xmlns', 'http://www.w3.org/2001/SMIL20/Language')
        head = SubElement(root, 'head')
        meta = SubElement(head, 'meta base="rtmp://cp23636.edgefcs.net/ondemand"')
        body = SubElement(root, 'body')

        switch_tag = ElementTree.SubElement(body, 'switch')

        for suffix, bitrate in video_data:
            attrs = {'src': ("mp4:soundcheck/{year}/{id}/{file_root_name}_{suffix}.mp4"
                             .format(suffix=str(suffix), **row)),
                     'system-bitrate': str(bitrate),
                     }
            ElementTree.SubElement(switch_tag, 'video', attrs)

        file_root_name = row["file_root_name"]
        year = row["year"]
        id = row["id"]
        path = year+'-'+id

        file_name = row['file_root_name']+'.smil'
        full_path = os.path.join(path, file_name)
        output = open(full_path, 'w')
        output.write(prettify(doctype, root))
4 голоса | спросил David Vasandani 31 SatEurope/Moscow2011-12-31T03:29:43+04:00Europe/Moscow12bEurope/MoscowSat, 31 Dec 2011 03:29:43 +0400 2011, 03:29:43

2 ответа


0

Изучив ваш текущий сценарий и другие вопросы, которые вы задавали по этому вопросу, я думаю, вы могли бы упростить свою жизнь, создав файлы smil с помощью манипуляции со строками.

Почти все xml в ваших файлах статичны. Единственные данные, о которых вам нужно заботиться, - это значения атрибутов для тега video. И для этого в стандартной библиотеке есть удобная функция, которая делает именно то, что вам нужно: xml.sax.saxutils.quoteattr .

Итак, учитывая эти моменты, вот сценарий, с которым должно быть намного проще работать:

import sys, os, csv
from xml.sax.saxutils import quoteattr

smil_header = '''\
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE smil PUBLIC "-//W3C//DTD SMIL 2.0//EN" "http://www.w3.org/2001/SMIL20/SMIL20.dtd">
<smil xmlns="http://www.w3.org/2001/SMIL20/Language">
  <head>
    <meta base="rtmp://cp23636.edgefcs.net/ondemand"/>
  </head>
  <body>
    <switch>
'''
smil_video = '''\
      <video src=%s system-bitrate=%s/>
'''
smil_footer = '''\
    </switch>
  </body>
</smil>
'''

src_format = 'mp4:soundcheck/%(year)s/%(id)s/%(file_root_name)s_%(suffix)s.mp4'

video_data = (
    ('256', '336000'), ('512', '592000'),
    ('768', '848000'), ('1128', '1208000'),
    )

root = os.getcwd()
if len(sys.argv) > 2:
    root = sys.argv[2]

with open(sys.argv[1], 'rU') as stream:

    for row in csv.DictReader(stream):
        smil = [smil_header]
        for suffix, bitrate in video_data:
            row['suffix'] = suffix
            smil.append(smil_video % (
                quoteattr(src_format) % row, quoteattr(bitrate)
                ))
        smil.append(smil_footer)

        directory = os.path.join(root, '%(year)s-%(id)s' % row)
        try:
            os.makedirs(directory)
        except OSError:
            pass
        path = os.path.join(directory, '%(file_root_name)s.smil' % row)
        print ':: writing file:', path
        with open(path, 'wb') as stream:
            stream.write(''.join(smil))
ответил ekhumoro 1 Jam1000000amSun, 01 Jan 2012 00:23:16 +040012 2012, 00:23:16
0

Я думаю, у вас есть как минимум три варианта:

  1. Просто примите новые строки. Они могут быть нежелательными и безобразными, но они совершенно законны.

  2. Добавьте kludge, который заменяет плохой DOCTYPE более хорошим. Возможно, что-то вроде этого:

       
     import re
    
    pretty_xml = prettify(doctype, elem)
    m = re.search("(<!.*dtd'>)", pretty_xml, re.DOTALL)
    ugly_doctype = m.group() 
    fixed_xml = pretty_xml.replace(ugly_doctype, doctype)
    
  3. Используйте более многофункциональный пакет XML. На ум приходят lxml ; это в основном совместимо с ElementTree. Используя tostring , вам не понадобится функция prettify, и DOCTYPE выходит так, как вы этого хотите , Пример:

       
     from lxml import etree 
    
    doctype = '<!DOCTYPE smil PUBLIC "-//W3C//DTD SMIL 2.0//EN" "http://www.w3.org/2001/SMIL20/SMIL20.dtd">'
    
    XML = '<smil xmlns="http://www.w3.org/2001/SMIL20/Language"><head><meta base="rtmp://cp23636.edgefcs.net/ondemand"/></head><body><switch><video src="mp4:soundcheck/1/clay_aiken/02_sc_ca_sorry_256.mp4" system-bitrate="336000"/><video src="mp4:soundcheck/1/clay_aiken/02_sc_ca_sorry_512.mp4" system-bitrate="592000"/><video src="mp4:soundcheck/1/clay_aiken/02_sc_ca_sorry_768.mp4" system-bitrate="848000"/><video src="mp4:soundcheck/1/clay_aiken/02_sc_ca_sorry_1128.mp4" system-bitrate="1208000"/></switch></body></smil>'
    
    elem = etree.fromstring(XML)
    print etree.tostring(elem, doctype=doctype, pretty_print=True,
                         xml_declaration=True, encoding="utf-8")
    

    Вывод:

    <?xml version='1.0' encoding='utf-8'?>
    <!DOCTYPE smil PUBLIC "-//W3C//DTD SMIL 2.0//EN" "http://www.w3.org/2001/SMIL20/SMIL20.dtd">
    <smil xmlns="http://www.w3.org/2001/SMIL20/Language">
      <head>
        <meta base="rtmp://cp23636.edgefcs.net/ondemand"/>
      </head>
      <body>
        <switch>
          <video src="mp4:soundcheck/1/clay_aiken/02_sc_ca_sorry_256.mp4" system-bitrate="336000"/>
          <video src="mp4:soundcheck/1/clay_aiken/02_sc_ca_sorry_512.mp4" system-bitrate="592000"/>
          <video src="mp4:soundcheck/1/clay_aiken/02_sc_ca_sorry_768.mp4" system-bitrate="848000"/>
          <video src="mp4:soundcheck/1/clay_aiken/02_sc_ca_sorry_1128.mp4" system-bitrate="1208000"/>
        </switch>
      </body>
    </smil>
    
ответил mzjn 31 SatEurope/Moscow2011-12-31T17:57:35+04:00Europe/Moscow12bEurope/MoscowSat, 31 Dec 2011 17:57:35 +0400 2011, 17:57:35

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132