XSLT:在重新排列 XML 时面临多个父节点的问题
Posted
技术标签:
【中文标题】XSLT:在重新排列 XML 时面临多个父节点的问题【英文标题】:XSLT: Facing issue with multiple parent nodes in while re-arranging XML 【发布时间】:2021-10-31 03:57:33 【问题描述】:我正在使用下面的 XSLT 根据有效日期重新排列/收集 XML 中的各种节点。
这是 XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<CompoundEmployee>
<xsl:variable name="var_person" select="//person/*[not(name()='personal_information') and not(name()='phone_information') and not(name()='email_information') and not(name()='employment_information')]"></xsl:variable>
<xsl:for-each select="//StartDate">
<xsl:variable name="i" select="position()"/>
<xsl:variable name="newDate" select="replace(//StartDate[$i],'-','')"/>
<Record>
<xsl:copy-of select="//StartDate[$i]"/>
<xsl:copy-of select="$var_person"/>
<xsl:copy-of select="//CompoundEmployee/person/personal_information[replace(start_date,'-','') <= $newDate and $newDate <= replace(end_date,'-','')]"/>
<xsl:copy-of select="//CompoundEmployee/person/employment_information/job_information[replace(start_date,'-','') <= $newDate and $newDate <= replace(end_date,'-','')]"/>
<xsl:copy-of select="//CompoundEmployee/person/employment_information[(replace(start_date,'-','') <= $newDate and ($newDate <= replace(end_date,'-','') or not(end_date)))]"/>
</Record>
</xsl:for-each>
</CompoundEmployee>
</xsl:template>
</xsl:stylesheet>
只要只有一个 CompoundEmployee 节点,它就可以正常工作。但我可以在根查询CompoundEmployeeResponse 中获得多个 CompoundEmployee 节点。这是输入 XML:
<?xml version="1.0" encoding="UTF-8"?>
<queryCompoundEmployeeResponse>
<CompoundEmployee>
<id>176</id>
<person>
<action>NO CHANGE</action>
<created_by>CONV_ADMIN</created_by>
<logon_user_id>1234567</logon_user_id>
<logon_user_is_active>true</logon_user_is_active>
<person_id>176</person_id>
<person_id_external>1234567</person_id_external>
<personal_information>
<end_date>9999-12-31</end_date>
<first_name>yutaka</first_name>
<first_name_previous>Robbin</first_name_previous>
<first_name_alt1>Robbin</first_name_alt1>
<start_date>2021-06-03</start_date>
</personal_information>
<personal_information>
<end_date>2021-06-02</end_date>
<first_name>wataru</first_name>
<first_name_previous>Robbin</first_name_previous>
<first_name_alt1>Robbin</first_name_alt1>
<start_date>2017-12-06</start_date>
</personal_information>
<employment_information>
<employment_id>136</employment_id>
<start_date>2017-12-06</start_date>
<user_id>10005005</user_id>
<job_information>
<action>NO CHANGE</action>
<end_date>9999-12-31</end_date>
<entry_into_group>2017-12-06</entry_into_group>
<event>5</event>
<event_reason>DATACONV</event_reason>
<excl_executive_sector>false</excl_executive_sector>
<fte>1.0</fte>
<hazard>false</hazard>
<job_code>1000039</job_code>
<location>10000069</location>
<manager_employment_id>265</manager_employment_id>
<manager_id>10005069</manager_id>
<manager_person_id>305</manager_person_id>
<manager_person_id_external>10005069</manager_person_id_external>
<start_date>2019-03-02</start_date>
</job_information>
</employment_information>
</person>
<StartDates>
<StartDate>2021-06-03</StartDate>
<StartDate>2017-12-06</StartDate>
<StartDate>2017-12-06</StartDate>
<StartDate>2019-03-02</StartDate>
</StartDates>
</CompoundEmployee>
<CompoundEmployee>
<id>176</id>
<person>
<action>NO CHANGE</action>
<created_by>CONV_ADMIN</created_by>
<logon_user_id>1234567</logon_user_id>
<logon_user_is_active>true</logon_user_is_active>
<person_id>176</person_id>
<person_id_external>1234567</person_id_external>
<personal_information>
<end_date>9999-12-31</end_date>
<first_name>yutaka</first_name>
<first_name_previous>Robbin</first_name_previous>
<first_name_alt1>Robbin</first_name_alt1>
<start_date>2021-06-03</start_date>
</personal_information>
<personal_information>
<end_date>2021-06-02</end_date>
<first_name>wataru</first_name>
<first_name_previous>Robbin</first_name_previous>
<first_name_alt1>Robbin</first_name_alt1>
<start_date>2017-12-06</start_date>
</personal_information>
<employment_information>
<employment_id>136</employment_id>
<start_date>2017-12-06</start_date>
<user_id>10005005</user_id>
<job_information>
<action>NO CHANGE</action>
<end_date>9999-12-31</end_date>
<entry_into_group>2017-12-06</entry_into_group>
<event>5</event>
<event_reason>DATACONV</event_reason>
<excl_executive_sector>false</excl_executive_sector>
<fte>1.0</fte>
<hazard>false</hazard>
<job_code>1000039</job_code>
<location>10000069</location>
<manager_employment_id>265</manager_employment_id>
<manager_id>10005069</manager_id>
<manager_person_id>305</manager_person_id>
<manager_person_id_external>10005069</manager_person_id_external>
<start_date>2019-03-02</start_date>
</job_information>
</employment_information>
</person>
<StartDates>
<StartDate>2021-06-01</StartDate>
<StartDate>2017-12-05</StartDate>
<StartDate>2017-12-07</StartDate>
<StartDate>2019-03-08</StartDate>
</StartDates>
</CompoundEmployee>
</queryCompoundEmployeeResponse>
错误: 在第 12 行执行 XSLT 时出错:不允许将多个项目的序列作为 fn:replace() ("2021-06-03", "2021-06-03") 的第一个参数
预期的 XML
<?xml version="1.0" encoding="UTF-8"?>
<queryCompoundEmployeeResponse>
<CompoundEmployee>
<Record>
<StartDate>2021-06-03</StartDate>
<action>NO CHANGE</action>
<created_by>CONV_ADMIN</created_by>
<logon_user_id>1234567</logon_user_id>
<logon_user_is_active>true</logon_user_is_active>
<person_id>176</person_id>
<person_id_external>1234567</person_id_external>
<personal_information>
<end_date>9999-12-31</end_date>
<first_name>yutaka</first_name>
<first_name_previous>Robbin</first_name_previous>
<first_name_alt1>Robbin</first_name_alt1>
<start_date>2021-06-03</start_date>
</personal_information>
<job_information>
<action>NO CHANGE</action>
<end_date>9999-12-31</end_date>
<entry_into_group>2017-12-06</entry_into_group>
<event>5</event>
<event_reason>DATACONV</event_reason>
<excl_executive_sector>false</excl_executive_sector>
<fte>1.0</fte>
<hazard>false</hazard>
<job_code>1000039</job_code>
<location>10000069</location>
<manager_employment_id>265</manager_employment_id>
<manager_id>10005069</manager_id>
<manager_person_id>305</manager_person_id>
<manager_person_id_external>10005069</manager_person_id_external>
<start_date>2019-03-02</start_date>
</job_information>
<employment_information>
<employment_id>136</employment_id>
<start_date>2017-12-06</start_date>
<user_id>10005005</user_id>
<job_information>
<action>NO CHANGE</action>
<end_date>9999-12-31</end_date>
<entry_into_group>2017-12-06</entry_into_group>
<event>5</event>
<event_reason>DATACONV</event_reason>
<excl_executive_sector>false</excl_executive_sector>
<fte>1.0</fte>
<hazard>false</hazard>
<job_code>1000039</job_code>
<location>10000069</location>
<manager_employment_id>265</manager_employment_id>
<manager_id>10005069</manager_id>
<manager_person_id>305</manager_person_id>
<manager_person_id_external>10005069</manager_person_id_external>
<start_date>2019-03-02</start_date>
</job_information>
</employment_information>
</Record>
<Record>
<StartDate>2017-12-06</StartDate>
<action>NO CHANGE</action>
<created_by>CONV_ADMIN</created_by>
<logon_user_id>1234567</logon_user_id>
<logon_user_is_active>true</logon_user_is_active>
<person_id>176</person_id>
<person_id_external>1234567</person_id_external>
<personal_information>
<end_date>2021-06-02</end_date>
<first_name>wataru</first_name>
<first_name_previous>Robbin</first_name_previous>
<first_name_alt1>Robbin</first_name_alt1>
<start_date>2017-12-06</start_date>
</personal_information>
<employment_information>
<employment_id>136</employment_id>
<start_date>2017-12-06</start_date>
<user_id>10005005</user_id>
<job_information>
<action>NO CHANGE</action>
<end_date>9999-12-31</end_date>
<entry_into_group>2017-12-06</entry_into_group>
<event>5</event>
<event_reason>DATACONV</event_reason>
<excl_executive_sector>false</excl_executive_sector>
<fte>1.0</fte>
<hazard>false</hazard>
<job_code>1000039</job_code>
<location>10000069</location>
<manager_employment_id>265</manager_employment_id>
<manager_id>10005069</manager_id>
<manager_person_id>305</manager_person_id>
<manager_person_id_external>10005069</manager_person_id_external>
<start_date>2019-03-02</start_date>
</job_information>
</employment_information>
</Record>
<Record>
<StartDate>2017-12-06</StartDate>
<action>NO CHANGE</action>
<created_by>CONV_ADMIN</created_by>
<logon_user_id>1234567</logon_user_id>
<logon_user_is_active>true</logon_user_is_active>
<person_id>176</person_id>
<person_id_external>1234567</person_id_external>
<personal_information>
<end_date>2021-06-02</end_date>
<first_name>wataru</first_name>
<first_name_previous>Robbin</first_name_previous>
<first_name_alt1>Robbin</first_name_alt1>
<start_date>2017-12-06</start_date>
</personal_information>
<employment_information>
<employment_id>136</employment_id>
<start_date>2017-12-06</start_date>
<user_id>10005005</user_id>
<job_information>
<action>NO CHANGE</action>
<end_date>9999-12-31</end_date>
<entry_into_group>2017-12-06</entry_into_group>
<event>5</event>
<event_reason>DATACONV</event_reason>
<excl_executive_sector>false</excl_executive_sector>
<fte>1.0</fte>
<hazard>false</hazard>
<job_code>1000039</job_code>
<location>10000069</location>
<manager_employment_id>265</manager_employment_id>
<manager_id>10005069</manager_id>
<manager_person_id>305</manager_person_id>
<manager_person_id_external>10005069</manager_person_id_external>
<start_date>2019-03-02</start_date>
</job_information>
</employment_information>
</Record>
<Record>
<StartDate>2019-03-02</StartDate>
<action>NO CHANGE</action>
<created_by>CONV_ADMIN</created_by>
<logon_user_id>1234567</logon_user_id>
<logon_user_is_active>true</logon_user_is_active>
<person_id>176</person_id>
<person_id_external>1234567</person_id_external>
<personal_information>
<end_date>2021-06-02</end_date>
<first_name>wataru</first_name>
<first_name_previous>Robbin</first_name_previous>
<first_name_alt1>Robbin</first_name_alt1>
<start_date>2017-12-06</start_date>
</personal_information>
<job_information>
<action>NO CHANGE</action>
<end_date>9999-12-31</end_date>
<entry_into_group>2017-12-06</entry_into_group>
<event>5</event>
<event_reason>DATACONV</event_reason>
<excl_executive_sector>false</excl_executive_sector>
<fte>1.0</fte>
<hazard>false</hazard>
<job_code>1000039</job_code>
<location>10000069</location>
<manager_employment_id>265</manager_employment_id>
<manager_id>10005069</manager_id>
<manager_person_id>305</manager_person_id>
<manager_person_id_external>10005069</manager_person_id_external>
<start_date>2019-03-02</start_date>
</job_information>
<employment_information>
<employment_id>136</employment_id>
<start_date>2017-12-06</start_date>
<user_id>10005005</user_id>
<job_information>
<action>NO CHANGE</action>
<end_date>9999-12-31</end_date>
<entry_into_group>2017-12-06</entry_into_group>
<event>5</event>
<event_reason>DATACONV</event_reason>
<excl_executive_sector>false</excl_executive_sector>
<fte>1.0</fte>
<hazard>false</hazard>
<job_code>1000039</job_code>
<location>10000069</location>
<manager_employment_id>265</manager_employment_id>
<manager_id>10005069</manager_id>
<manager_person_id>305</manager_person_id>
<manager_person_id_external>10005069</manager_person_id_external>
<start_date>2019-03-02</start_date>
</job_information>
</employment_information>
</Record>
</CompoundEmployee>
<CompoundEmployee>
<Record>
<StartDate>2021-06-01</StartDate>
<action>NO CHANGE</action>
<created_by>CONV_ADMIN</created_by>
<logon_user_id>1234567</logon_user_id>
<logon_user_is_active>true</logon_user_is_active>
<person_id>176</person_id>
<person_id_external>1234567</person_id_external>
<personal_information>
<end_date>9999-12-31</end_date>
<first_name>yutaka</first_name>
<first_name_previous>Robbin</first_name_previous>
<first_name_alt1>Robbin</first_name_alt1>
<start_date>2021-06-01</start_date>
</personal_information>
<personal_information>
<end_date>2021-06-02</end_date>
<first_name>wataru</first_name>
<first_name_previous>Robbin</first_name_previous>
<first_name_alt1>Robbin</first_name_alt1>
<start_date>2017-12-05</start_date>
</personal_information>
<job_information>
<action>NO CHANGE</action>
<end_date>9999-12-31</end_date>
<entry_into_group>2017-12-06</entry_into_group>
<event>5</event>
<event_reason>DATACONV</event_reason>
<excl_executive_sector>false</excl_executive_sector>
<fte>1.0</fte>
<hazard>false</hazard>
<job_code>1000039</job_code>
<location>10000069</location>
<manager_employment_id>265</manager_employment_id>
<manager_id>10005069</manager_id>
<manager_person_id>305</manager_person_id>
<manager_person_id_external>10005069</manager_person_id_external>
<start_date>2019-03-08</start_date>
</job_information>
<employment_information>
<employment_id>136</employment_id>
<start_date>2017-12-07</start_date>
<user_id>10005005</user_id>
<job_information>
<action>NO CHANGE</action>
<end_date>9999-12-31</end_date>
<entry_into_group>2017-12-06</entry_into_group>
<event>5</event>
<event_reason>DATACONV</event_reason>
<excl_executive_sector>false</excl_executive_sector>
<fte>1.0</fte>
<hazard>false</hazard>
<job_code>1000039</job_code>
<location>10000069</location>
<manager_employment_id>265</manager_employment_id>
<manager_id>10005069</manager_id>
<manager_person_id>305</manager_person_id>
<manager_person_id_external>10005069</manager_person_id_external>
<start_date>2019-03-08</start_date>
</job_information>
</employment_information>
</Record>
<Record>
<StartDate>2017-12-05</StartDate>
<action>NO CHANGE</action>
<created_by>CONV_ADMIN</created_by>
<logon_user_id>1234567</logon_user_id>
<logon_user_is_active>true</logon_user_is_active>
<person_id>176</person_id>
<person_id_external>1234567</person_id_external>
<personal_information>
<end_date>2021-06-02</end_date>
<first_name>wataru</first_name>
<first_name_previous>Robbin</first_name_previous>
<first_name_alt1>Robbin</first_name_alt1>
<start_date>2017-12-05</start_date>
</personal_information>
</Record>
<Record>
<StartDate>2017-12-07</StartDate>
<action>NO CHANGE</action>
<created_by>CONV_ADMIN</created_by>
<logon_user_id>1234567</logon_user_id>
<logon_user_is_active>true</logon_user_is_active>
<person_id>176</person_id>
<person_id_external>1234567</person_id_external>
<personal_information>
<end_date>2021-06-02</end_date>
<first_name>wataru</first_name>
<first_name_previous>Robbin</first_name_previous>
<first_name_alt1>Robbin</first_name_alt1>
<start_date>2017-12-05</start_date>
</personal_information>
<employment_information>
<employment_id>136</employment_id>
<start_date>2017-12-07</start_date>
<user_id>10005005</user_id>
<job_information>
<action>NO CHANGE</action>
<end_date>9999-12-31</end_date>
<entry_into_group>2017-12-06</entry_into_group>
<event>5</event>
<event_reason>DATACONV</event_reason>
<excl_executive_sector>false</excl_executive_sector>
<fte>1.0</fte>
<hazard>false</hazard>
<job_code>1000039</job_code>
<location>10000069</location>
<manager_employment_id>265</manager_employment_id>
<manager_id>10005069</manager_id>
<manager_person_id>305</manager_person_id>
<manager_person_id_external>10005069</manager_person_id_external>
<start_date>2019-03-08</start_date>
</job_information>
</employment_information>
</Record>
<Record>
<StartDate>2019-03-08</StartDate>
<action>NO CHANGE</action>
<created_by>CONV_ADMIN</created_by>
<logon_user_id>1234567</logon_user_id>
<logon_user_is_active>true</logon_user_is_active>
<person_id>176</person_id>
<person_id_external>1234567</person_id_external>
<personal_information>
<end_date>2021-06-02</end_date>
<first_name>wataru</first_name>
<first_name_previous>Robbin</first_name_previous>
<first_name_alt1>Robbin</first_name_alt1>
<start_date>2017-12-05</start_date>
</personal_information>
<job_information>
<action>NO CHANGE</action>
<end_date>9999-12-31</end_date>
<entry_into_group>2017-12-06</entry_into_group>
<event>5</event>
<event_reason>DATACONV</event_reason>
<excl_executive_sector>false</excl_executive_sector>
<fte>1.0</fte>
<hazard>false</hazard>
<job_code>1000039</job_code>
<location>10000069</location>
<manager_employment_id>265</manager_employment_id>
<manager_id>10005069</manager_id>
<manager_person_id>305</manager_person_id>
<manager_person_id_external>10005069</manager_person_id_external>
<start_date>2019-03-08</start_date>
</job_information>
<employment_information>
<employment_id>136</employment_id>
<start_date>2017-12-07</start_date>
<user_id>10005005</user_id>
<job_information>
<action>NO CHANGE</action>
<end_date>9999-12-31</end_date>
<entry_into_group>2017-12-06</entry_into_group>
<event>5</event>
<event_reason>DATACONV</event_reason>
<excl_executive_sector>false</excl_executive_sector>
<fte>1.0</fte>
<hazard>false</hazard>
<job_code>1000039</job_code>
<location>10000069</location>
<manager_employment_id>265</manager_employment_id>
<manager_id>10005069</manager_id>
<manager_person_id>305</manager_person_id>
<manager_person_id_external>10005069</manager_person_id_external>
<start_date>2019-03-08</start_date>
</job_information>
</employment_information>
</Record>
</CompoundEmployee>
即使有多个 CompoundEmployee 节点,我也需要让它工作。另外,请让我知道是否有更好的方法来做到这一点。我通过浏览一些博客创建了这个。谢谢!
【问题讨论】:
究竟什么是“不”工作?你有错误吗?如果有,具体是哪一个?你得到错误的结果吗?然后显示想要的结果和当前的结果。 用无效的 XML 更新了问题。还添加了错误。如果 XML 只有一个 CompoundEmployee,XSLT 就可以工作,在这种情况下,它会生成一个 XML,其中有 1 个 CompoundEmployee 节点,有 4 个“记录”。预期的 XML 应该有 2 个 CompoundEmployee 节点,每个节点有 4 条记录。 请编辑您的问题并添加预期的输出。请注意,如果您为输入中的每个 CompoundEmployee 创建一个 CompoundEmployee 节点,则需要添加一个根元素 - 否则您的结果将不是一个格式良好的 XML 文档。 正如我所说,您发布的是一个 XML 片段。确定这是您想要的吗? 添加了预期的 XML。好的,可以添加一个根元素,我可以稍后处理。谢谢! 【参考方案1】:通常我会建议使用模板匹配和相对于匹配元素的路径,例如
<xsl:template match="CompoundEmployee">
<xsl:copy>
<xsl:for-each select=".//StartDate">
或者更好的更多模板,例如
<xsl:template match="CompoundEmployee">
<xsl:copy>
<xsl:apply-templates select=".//StartDate"/>
</xsl:copy>
</xsl:template>
和
<xsl:template match="StartDate">
<Record>
<xsl:copy-of select="."/> <!-- copies the match StartDate element -->
...
</Record>
</xsl:template>
【讨论】:
【参考方案2】:恕我直言,您将可能相对简单的事情复杂化了。
试试这个作为你的起点:
XSLT 2.0
<xsl:stylesheet version="2.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="/queryCompoundEmployeeResponse">
<root>
<xsl:for-each select="CompoundEmployee">
<xsl:copy>
<xsl:variable name="person" select="person" />
<xsl:for-each select="StartDates/StartDate">
<Record>
<xsl:copy-of select="."/>
<xsl:copy-of select="$person/* except $person/(personal_information | phone_information | email_information | employment_information)"/>
<!-- copy relevant personal information -->
<xsl:copy-of select="$person/personal_information[start_date le current() and current() le end_date]"/>
<!-- do the same for the other types of information -->
</Record>
</xsl:for-each>
</xsl:copy>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
【讨论】:
这正是我所需要的。不知道 current(),比使用索引方便得多。非常感谢..!以上是关于XSLT:在重新排列 XML 时面临多个父节点的问题的主要内容,如果未能解决你的问题,请参考以下文章