2016-05-01 2 views
3

У меня есть три файла XML (примеры ниже). Я назвал файлы соответствующими значениями атрибута audioId. Таким образом, файлы в вопрос будет называться 93.xml и 2137.xml:Исследуйте специфический XML-атрибут из одного файла и добавьте его в другой, если другой атрибут присутствует во втором файле

93.xml:

<word BloomsTaxonomy="1,2,3" DictationGroupid="i-e combination List 7" Stage="0" Use="P,L" audioId="93" /> 

2173.xml:

<word BloomsTaxonomy="1,2,3" DictationGroupid="i-e combination List 7" Stage="0" Use="P,L" audioId="2137" /> 

mainDataSet.xml:

<word id="2137" title="over" level="1" grouping="Sight Words" YRule="0" MagicE="0" SoftC="0" doublevowel="0" longvowel="0" displayorder="101" silentletters="0"/> 

Файл mainDataSet.xml содержит ~ 3000 записей. Я только предоставил одну запись для этого вопроса.

Мой вопрос о том, как я хотел бы добавить атрибут title из mainDataSet.xml в word тег в 2173.xml из mainDataSet.xml если id матчи в обоих файлах (или даже если id в mainDataSet.xml соответствует файл имя). Например, в образцах, я обеспечил, вывод должен быть:

<word BloomsTaxonomy="1,2,3" DictationGroupid="i-e combination List 7" Stage="0" Use="P,L" audioId="2137" title="over" /> 

Чтобы разобрать мой XML из mainDataSet.xml, я сейчас делаю:

e = xml.etree.ElementTree.parse('mainDataSet.xml').getroot() 
for atype in e.findall('word'): 
    print(atype.get('title')) 

ответ

2

Чтобы добавить атрибут, используйте .attrib словарь. Вот пример кода, который перебирает word элементов внутри mainDataSet.xml, извлекает значение по id атрибута, разбирает соответствующий XML-файл (93.xml и 2173.xml в данном случае), обновляет word элемент и выводит дерево обратно в файл:

import xml.etree.ElementTree as ET 


e = ET.parse('mainDataSet.xml').getroot() 
for word in e.findall('word'): 
    word_id = word.attrib.get("id") 
    if word_id: 
     filename = "%s.xml" % word_id 
     e_word = ET.parse(filename) 
     e_word.getroot().attrib['title'] = word.attrib.get('title') 
     e_word.write(filename) 

образец mainDataSet.xml, что я использовал:

<words> 
    <word id="2137" title="over" level="1" grouping="Sight Words" YRule="0" MagicE="0" SoftC="0" doublevowel="0" longvowel="0" displayorder="101" silentletters="0"/> 
    <word id="93" title="something else" level="1" grouping="Sight Words" YRule="0" MagicE="0" SoftC="0" doublevowel="0" longvowel="0" displayorder="101" silentletters="0"/> 
</words> 

Вот что я получил после выполнения сценария:

  • 93.xml:

    <word BloomsTaxonomy="1,2,3" DictationGroupid="i-e combination List 7" Stage="0" Use="P,L" audioId="93" title="something else" /> 
    
  • 2173.xml:

    <word BloomsTaxonomy="1,2,3" DictationGroupid="i-e combination List 7" Stage="0" Use="P,L" audioId="2137" title="over" /> 
    
+0

Совершенная. Danke! Я пройду через это и дам вам знать, как это происходит! – thel3l

2

Для ОП или будущих читателей, рассмотрим XSLT 1.0 решение, которое Python может работать с использованием lxml модуля. Как информация, XSLT является языком специального назначения (чей скрипт является хорошо сформированным XML-файлом), предназначенным для работы с XML-файлами. Сценарий переносится на другие языки общего назначения (Java, PHP, C#), XSLT-процессоры (Saxon, Xalan), даже интерпретаторы командной строки (Bash, PowerShell). В частности, для этого вопроса XSLT поддерживает функцию document(), которая может обращаться к узлам во внешних xml-файлах для удовлетворения потребностей сравнения, таких как идентификаторы.

Входной(добавление корневых тегов)

mainDataSet.xml

<root> 
    <word id="2137" title="over" level="1" grouping="Sight Words" YRule="0" 
     MagicE="0" SoftC="0" doublevowel="0" longvowel="0" 
     displayorder="101" silentletters="0"/> 
</root> 

2137.xml

<root> 
    <word BloomsTaxonomy="1,2,3" DictationGroupid="i-e combination List 7" 
      Stage="0" Use="P,L" audioId="2137" /> 
</root> 

93.xml

<root> 
    <word BloomsTaxonomy="1,2,3" DictationGroupid="i-e combination List 7" 
     Stage="0" Use="P,L" audioId="93" /> 
</root> 

XSLT Сценарий (сэкономьте внешне как .xsl; читать .py; предполагается, что все XML-файлы находятся в том же каталоге)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > 
    <xsl:output method="xml" indent="yes" encoding="UTF-8" /> 

    <xsl:template match="root"> 
    <xsl:copy> 
     <xsl:apply-templates select="word"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="word">  
    <xsl:copy> 
     <xsl:copy-of select="@*"/> 
     <xsl:if test="@audioId = document('mainDataSet.xml')/root/word/@id"> 
     <xsl:attribute name="title"> 
      <xsl:value-of select="document('mainDataSet.xml')/root/word/@title"/> 
     </xsl:attribute> 
     </xsl:if> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

Python Script

import lxml.etree as ET 

# LOAD XML AND XSL 
xslt = ET.parse('XSLTScript.xsl') 
for i in ['2137', '93']: 
    dom = ET.parse('{}.xml'.format(i)) 

    # TRANSFORM XML 
    transform = ET.XSLT(xslt) 
    newdom = transform(dom) 

    # PRETTY PRINT OUTPUT 
    tree_out = ET.tostring(newdom, encoding='UTF-8', pretty_print=True) 
    print(tree_out.decode("utf-8")) 

    # SAVE TO FILE 
    xmlfile = open('{}.xml'.format(i),'wb') 
    xmlfile.write(tree_out) 
    xmlfile.close() 

Выход(используя переданные данные)

2173.xml

<root> 
    <word BloomsTaxonomy="1,2,3" DictationGroupid="i-e combination List 7" Stage="0" 
     Use="P,L" audioId="2137" title="over"/> 
</root> 

93.xml

<root> 
    <word BloomsTaxonomy="1,2,3" DictationGroupid="i-e combination List 7" Stage="0" 
     Use="P,L" audioId="93"/> 
</root> 
+0

Purr-fect. Оба эти решения работают! Я пройду через них и дам вам знать. Danke! – thel3l

+0

Я закончил с использованием решения @alecxe. Это тоже неплохая идея! Спасибо всем! – thel3l