Я проектирую какой-то конвейер ETL, в котором я хотел бы сначала разбить входной набор данных XML на отдельные файлы XML, связанные с каждым элементом. Входные наборы данных - это в основном экспорт метаданных по конкретным моделям (текущий пример - EDM). Мне довольно комфортно с XSLT, и я надеялся использовать это, чтобы избежать слишком большого количества Python в этом вопросе, который, предположительно, не настолько сложен.
Я просмотрел много потоков, в том числе Fast_iter Лизы Дейли (см. https://www.ibm.com/developerworks/xml/library/x-hiperfparse/).). Я пробовал другой подход, но всегда застрял при записи файлов (без вывода или из-за проблем с сериализацией). Отзыв пожалуйста?!
Структура набора данных
<rdf:RDF ...many namespaces...>
<!--ITEM1 NODE-->
<ore:aggregates>
<edm:ProvidedCHO rdf:about="http://some/url"/>
<ore:Aggregation rdf:about="http://some/url">
<...>
</ore:Aggregation>
<ore:Proxy rdf:about="http://some/url">
<...>
</ore:Proxy>
<edm:EuropeanaAggregation rdf:about="http://some/url">
<...>
</edm:EuropeanaAggregation>
</ore:aggregates>
<!--ITEM2 NODE-->
<ore:aggregates>
<...>
</ore:aggregates>
<!--ITEM3 NODE-->
<ore:aggregates>
<...>
</ore:aggregates>
</rdf:RDF>
Ожидаемый результат
<!--ITEM 1-->
<rdf:RDF ...many namespaces...>
<edm:ProvidedCHO rdf:about="http://some/url"/>
<ore:Aggregation rdf:about="http://some/url">
<...>
</ore:Aggregation>
<ore:Proxy rdf:about="http://some/url">
<...>
</ore:Proxy>
<edm:EuropeanaAggregation rdf:about="http://some/url">
<...>
</edm:EuropeanaAggregation>
</rdf:RDF>
ТЕКУЩИЕ ПРОБЫ
Попытка использовать lxml для однократного применения XSLT для определения элементов (script + xslt)
from lxml import etree as ET
dom = ET.parse(source)
xslt = ET.parse(xsl_filename)
transform = ET.XSLT(xslt)
newdom = transform(dom)
print(ET.tostring(newdom, pretty_print=True))
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet exclude-result-prefixes="xsi xlink xml" version="2.0"
xmlns:many="namespaces">
<xsl:output encoding="UTF-8" indent="yes"/>
<!--<xsl:param name="output" select="'/Users/yep/Code/+dev/test data/output/'"/>-->
<xsl:param name="output" select="'/home/yep/data/split/'"/>
<xsl:param name="children" select="/rdf:RDF/ore:aggregates"/>
<!-- ROOT MATCH -->
<xsl:template match="/">
<xsl:for-each select="$children">
<xsl:call-template name="itemize"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="itemize">
<xsl:variable name="uri" select="translate(ore:Proxy/dc:identifier, ' ', '_')"/>
<xsl:variable name="ns"/>
<xsl:variable name="fullOutput" select="concat($output, $uri)"/>
<xsl:result-document href="{$fullOutput}.xml" method="xml">
<xsl:element name="rdf:RDF">
<xsl:copy-of select="namespace::*"/>
<xsl:copy-of select="*"/>
</xsl:element>
</xsl:result-document>
</xsl:template>
</xsl:stylesheet>
... нет вывода. Также пытался написать, но не работает
Попытка через ETree
import xml.etree.ElementTree as ET
root = ET.parse(source).getroot()
# namespaces variable generated from a json file
jsonFile = open("application/models/namespaces.json")
jsonStr = jsonFile.read()
namespaces = json.loads(jsonStr)
for item in root.findall("ore:aggregates",namespaces):
newTree = ET.parse("/home/yep/application/services/create/sample.xml")
newroot = newTree.getroot()
for node in item.findall("edm:ProvidedCHO",namespaces):
newroot.append(node)
ET.SubElement(newroot,node)
filename = "/home/yep/data/split/" + str(i) + ".xml"
newTree.write(filename)
TypeError: cannot serialize <Element '{http://www.europeana.eu/schemas/edm/}ProvidedCHO' at 0x7f4768a03688> (type Element)
Я думаю, что проблема связана с тем фактом, что я обрабатываю пространства имен неправильно или, может быть, потому, что я все еще использую XSLT-подход к данным, когда это Python ... некоторая помощь будет принята:)