基于数据帧生成具有条件输出的 XML 文件
Generating an XML file with conditional output based on a dataframe
我正在尝试生成一个基于数据帧的 XML 文件。 XML 输出的结构应包含一些一般信息,然后是交易列表,然后是一些结尾注释。棘手的一点是每种交易类型都需要不同的输出和父标签,这意味着我需要生成几个有条件执行的模板。数据看起来像这样:
secondary_info_1
transactionnumber
date_transaction
amount_local
from_country
to_country
transaction_type
gender
Some stuff goes here
trx001
2022-01-02
2883
DE
incoming_1
M
Some stuff goes here
trx003
2022-01-04
857
incoming_2
M
Some stuff goes here
trx004
2022-01-05
4
AT
outgoing_1
M
Some stuff goes here
trx006
2022-01-07
26
outgoing_2
M
所需的输出如下所示:
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<record>
<secondary_info_1>Some stuff goes here</secondary_info_1>
<incoming_transaction_1>
<transaction_from>
<transactionnumber>trxno001</transactionnumber>
<date_transaction>2022-01-02</date_transaction>
<amount_local>2883</amount_local>
<from_country>DE</from_country>
</transaction_from>
<transaction_to>
<personalia>
<gender>M</gender>
</personalia>
</transaction_to>
</incoming_transaction_1>
<incoming_transaction_2>
<transaction_from>
<transactionnumber>trxno003</transactionnumber>
<date_transaction>2022-01-04</date_transaction>
<amount_local>857</amount_local>
</transaction_from>
<transaction_to>
<personalia>
<gender>M</gender>
</personalia>
</transaction_to>
</incoming_transaction_2>
<outgoing_transaction_1>
<transaction_to>
<personalia>
<gender>M</gender>
</personalia>
</transaction_to>
<transaction_from>
<transactionnumber>trxno004</transactionnumber>
<date_transaction>2022-01-05</date_transaction>
<amount_local>4</amount_local>
<from_country>AT</from_country>
</transaction_from>
</outgoing_transaction_1>
<outgoing_transaction_2>
<transaction_to>
<personalia>
<gender>M</gender>
</personalia>
</transaction_to>
<transaction_from>
<transactionnumber>trxno006</transactionnumber>
<date_transaction>2022-01-07</date_transaction>
<amount_local>26</amount_local>
</transaction_from>
</outgoing_transaction_2>
<secondary_info_2>Some more stuff goes here</secondary_info_2>
</record>
简而言之,我们有一个交易概览,其中每个交易都附有个人资料,以及这些交易上方和下方的一些信息 (secondary_info_1/2
)。模板根据 transaction_type
列中的值更改。
我发现通过在 pandas.to_xml()
函数中使用样式表参数来生成一个更静态的 XML 确实效果很好,但是我很难创建一个有条件触发的模板。我尝试修改采用 here 的方法(单元格 366 和 367,就在“XML Final Notes”之前),但我不知道如何使用 <xsl_if test="transaction_type == 'incoming_1'">
等来触发我的不同有条件的交易模板。
有人可以帮忙吗?
编辑:所需输出的一般结构如下(上下文也作为标签中的文本添加):
<record>
<secondary_info>
<nested_secondary_info>A bunch of added information should go in this first section of the document</nested_secondary_info>
<incoming_transaction_1>
<incoming_nested_transaction_info_1>Some, but not all of the fields go here, and the structure changes based on the transaction type</incoming_nested_transaction_info_1>
</incoming_transaction_1>
<outgoing_transaction_1>
<outgoing_nested_transaction_info_2>For example, the "from_country" field should only be returned for incoming_transaction_1, and "to_country" should only be returned for "outgoing_transaction_1"</outgoing_nested_transaction_info_2>
</outgoing_transaction_1>
<incoming_transaction_2>
<incoming_nested_transaction_info_2>Ideally the transactions would also be sorted based on the date, but it seems that works as long as the dataframe is sorted correctly</incoming_nested_transaction_info_2>
</incoming_transaction_2>
<some_more_secondary_info>
<some_more_nested_secondary_info>I would also need to add some information to the end of this document as a sibling of the transactional information</some_more_nested_secondary_info>
</some_more_secondary_info>
</record>
由于对输出的特定要求,无论如何编写特定模板都会很痛苦。然而,我已经能够编写一个基本的 XSLT,使我能够生成事务概述:
<xsl:stylesheet version = "1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/data">
<report>
<xsl:apply-templates select="row"/>
</report>
</xsl:template>
<xsl:template match="row">
<xsl:choose>
<xsl:when test="transaction_type='incoming_1'">
<transaction_account_to_consumer>
<xsl:copy-of select="amount_local"/>
<t_from>
<xsl:copy-of select="from_country"/>
</t_from>
</transaction_account_to_consumer>
</xsl:when>
<xsl:when test="transaction_type='incoming_2'">
<transaction_entity_to_consumer>
<xsl:copy-of select="amount_local"/>
</transaction_entity_to_consumer>
</xsl:when>
<xsl:when test="transaction_type='outgoing_1'">
<transaction_consumer_to_account>
<t_to>
<xsl:copy-of select="to_country"/>
</t_to>
<xsl:copy-of select="amount_local"/>
</transaction_consumer_to_account>
</xsl:when>
<xsl:when test="transaction_type='outgoing_2'">
<transaction_consumer_to_entity>
<xsl:copy-of select="amount_local"/>
</transaction_consumer_to_entity>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
此模板会膨胀到数百行(每个交易类型子模板需要 >50 个标签),这很烦人,但可以管理。然而,一个更大的问题是,虽然我可以让条件模板为我的目的工作,但我不知道如何在交易信息的上方和下方添加我的 secondary_info。
如果我在 xsl:choose 之前添加它,它只是将它附加到每个交易之上,而我希望它只附加一次,在交易列表之前。
我解决这个问题的想法是只匹配不同模板中的 first 行,然后在 ,表示 XSLT 顶部的信息看起来更像这样:
<xsl:template match="/data">
<report>
<xsl:apply-templates select="first_row"/>
<xsl:apply-templates select="row"/>
<xsl:apply-templates select="first_row"/>
</report>
</xsl:template>
每个模板只会 select 数据框第一行中的某些字段。但是,两个“select="first_row"" 模板将 select 不同于交易概览第一行的 字段。
有什么方法可以实现吗?
可能很简单,你的测试语法有点不对,是test="transaction_type = 'incoming_1'"
,用=
,不是==
。
这是一个简单的 XSLT,如果 transaction_type 为 incoming_1,则仅保留 <row>
,main.xsl:
<?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" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="row">
<xsl:if test="transaction_type = 'incoming_1'">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
当我运行这个:
df = pd.read_csv('input.csv')
print(df.to_xml(stylesheet='main.xsl'))
我得到:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<row>
<index>0</index>
<secondary_info_1>Some stuff goes here</secondary_info_1>
<transactionnumber>trx001</transactionnumber>
<date_transaction>2022-01-02</date_transaction>
<amount_local>2883</amount_local>
<from_country>DE</from_country>
<to_country/>
<transaction_type>incoming_1</transaction_type>
<gender>M</gender>
</row>
</data>
我正在尝试生成一个基于数据帧的 XML 文件。 XML 输出的结构应包含一些一般信息,然后是交易列表,然后是一些结尾注释。棘手的一点是每种交易类型都需要不同的输出和父标签,这意味着我需要生成几个有条件执行的模板。数据看起来像这样:
secondary_info_1 | transactionnumber | date_transaction | amount_local | from_country | to_country | transaction_type | gender |
---|---|---|---|---|---|---|---|
Some stuff goes here | trx001 | 2022-01-02 | 2883 | DE | incoming_1 | M | |
Some stuff goes here | trx003 | 2022-01-04 | 857 | incoming_2 | M | ||
Some stuff goes here | trx004 | 2022-01-05 | 4 | AT | outgoing_1 | M | |
Some stuff goes here | trx006 | 2022-01-07 | 26 | outgoing_2 | M |
所需的输出如下所示:
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<record>
<secondary_info_1>Some stuff goes here</secondary_info_1>
<incoming_transaction_1>
<transaction_from>
<transactionnumber>trxno001</transactionnumber>
<date_transaction>2022-01-02</date_transaction>
<amount_local>2883</amount_local>
<from_country>DE</from_country>
</transaction_from>
<transaction_to>
<personalia>
<gender>M</gender>
</personalia>
</transaction_to>
</incoming_transaction_1>
<incoming_transaction_2>
<transaction_from>
<transactionnumber>trxno003</transactionnumber>
<date_transaction>2022-01-04</date_transaction>
<amount_local>857</amount_local>
</transaction_from>
<transaction_to>
<personalia>
<gender>M</gender>
</personalia>
</transaction_to>
</incoming_transaction_2>
<outgoing_transaction_1>
<transaction_to>
<personalia>
<gender>M</gender>
</personalia>
</transaction_to>
<transaction_from>
<transactionnumber>trxno004</transactionnumber>
<date_transaction>2022-01-05</date_transaction>
<amount_local>4</amount_local>
<from_country>AT</from_country>
</transaction_from>
</outgoing_transaction_1>
<outgoing_transaction_2>
<transaction_to>
<personalia>
<gender>M</gender>
</personalia>
</transaction_to>
<transaction_from>
<transactionnumber>trxno006</transactionnumber>
<date_transaction>2022-01-07</date_transaction>
<amount_local>26</amount_local>
</transaction_from>
</outgoing_transaction_2>
<secondary_info_2>Some more stuff goes here</secondary_info_2>
</record>
简而言之,我们有一个交易概览,其中每个交易都附有个人资料,以及这些交易上方和下方的一些信息 (secondary_info_1/2
)。模板根据 transaction_type
列中的值更改。
我发现通过在 pandas.to_xml()
函数中使用样式表参数来生成一个更静态的 XML 确实效果很好,但是我很难创建一个有条件触发的模板。我尝试修改采用 here 的方法(单元格 366 和 367,就在“XML Final Notes”之前),但我不知道如何使用 <xsl_if test="transaction_type == 'incoming_1'">
等来触发我的不同有条件的交易模板。
有人可以帮忙吗?
编辑:所需输出的一般结构如下(上下文也作为标签中的文本添加):
<record>
<secondary_info>
<nested_secondary_info>A bunch of added information should go in this first section of the document</nested_secondary_info>
<incoming_transaction_1>
<incoming_nested_transaction_info_1>Some, but not all of the fields go here, and the structure changes based on the transaction type</incoming_nested_transaction_info_1>
</incoming_transaction_1>
<outgoing_transaction_1>
<outgoing_nested_transaction_info_2>For example, the "from_country" field should only be returned for incoming_transaction_1, and "to_country" should only be returned for "outgoing_transaction_1"</outgoing_nested_transaction_info_2>
</outgoing_transaction_1>
<incoming_transaction_2>
<incoming_nested_transaction_info_2>Ideally the transactions would also be sorted based on the date, but it seems that works as long as the dataframe is sorted correctly</incoming_nested_transaction_info_2>
</incoming_transaction_2>
<some_more_secondary_info>
<some_more_nested_secondary_info>I would also need to add some information to the end of this document as a sibling of the transactional information</some_more_nested_secondary_info>
</some_more_secondary_info>
</record>
由于对输出的特定要求,无论如何编写特定模板都会很痛苦。然而,我已经能够编写一个基本的 XSLT,使我能够生成事务概述:
<xsl:stylesheet version = "1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/data">
<report>
<xsl:apply-templates select="row"/>
</report>
</xsl:template>
<xsl:template match="row">
<xsl:choose>
<xsl:when test="transaction_type='incoming_1'">
<transaction_account_to_consumer>
<xsl:copy-of select="amount_local"/>
<t_from>
<xsl:copy-of select="from_country"/>
</t_from>
</transaction_account_to_consumer>
</xsl:when>
<xsl:when test="transaction_type='incoming_2'">
<transaction_entity_to_consumer>
<xsl:copy-of select="amount_local"/>
</transaction_entity_to_consumer>
</xsl:when>
<xsl:when test="transaction_type='outgoing_1'">
<transaction_consumer_to_account>
<t_to>
<xsl:copy-of select="to_country"/>
</t_to>
<xsl:copy-of select="amount_local"/>
</transaction_consumer_to_account>
</xsl:when>
<xsl:when test="transaction_type='outgoing_2'">
<transaction_consumer_to_entity>
<xsl:copy-of select="amount_local"/>
</transaction_consumer_to_entity>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
此模板会膨胀到数百行(每个交易类型子模板需要 >50 个标签),这很烦人,但可以管理。然而,一个更大的问题是,虽然我可以让条件模板为我的目的工作,但我不知道如何在交易信息的上方和下方添加我的 secondary_info。
如果我在 xsl:choose 之前添加它,它只是将它附加到每个交易之上,而我希望它只附加一次,在交易列表之前。
我解决这个问题的想法是只匹配不同模板中的 first 行,然后在
<xsl:template match="/data">
<report>
<xsl:apply-templates select="first_row"/>
<xsl:apply-templates select="row"/>
<xsl:apply-templates select="first_row"/>
</report>
</xsl:template>
每个模板只会 select 数据框第一行中的某些字段。但是,两个“select="first_row"" 模板将 select 不同于交易概览第一行的 字段。
有什么方法可以实现吗?
可能很简单,你的测试语法有点不对,是test="transaction_type = 'incoming_1'"
,用=
,不是==
。
这是一个简单的 XSLT,如果 transaction_type 为 incoming_1,则仅保留 <row>
,main.xsl:
<?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" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="row">
<xsl:if test="transaction_type = 'incoming_1'">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
当我运行这个:
df = pd.read_csv('input.csv')
print(df.to_xml(stylesheet='main.xsl'))
我得到:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<row>
<index>0</index>
<secondary_info_1>Some stuff goes here</secondary_info_1>
<transactionnumber>trx001</transactionnumber>
<date_transaction>2022-01-02</date_transaction>
<amount_local>2883</amount_local>
<from_country>DE</from_country>
<to_country/>
<transaction_type>incoming_1</transaction_type>
<gender>M</gender>
</row>
</data>