XSL解析和重新排序XML节点

时间:2019-05-10 07:58:30

标签: xslt

在创建XSL样式表以解析数据并基于某些节点内的值进行重新排序时,我需要帮助。我的原始XML正在由名册程序以不希望的结构导出,这在转换为JSON时会引起问题。

这是消防部门的名册,将被转换为JSON,以便由车站状态委员会处理。我希望格式化XML,以便在转换为JSON时每个工作站都有一个工作人员列表。我尝试创建XSL失败。我的XSL(消防员)背景为零。

原始XML部分:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Data>
    <Date>2019-05-07-07:00</Date>
    <Headers></Headers>
    <Records>
        <Record>
            <RscPayrollIDCh>12345678</RscPayrollIDCh>
            <RscEmployeeIDCh>12345678</RscEmployeeIDCh>
            <RscMasterNameCh>Smith, Mike A.</RscMasterNameCh>
            <InstitutionAbrvCh>SPL</InstitutionAbrvCh>
            <AgencyAbrvCh>SPFD</AgencyAbrvCh>
            <RegionAbrvCh>OPS</RegionAbrvCh>
            <StationAbrvCh>B19</StationAbrvCh>
            <PUnitAbrvCh>BAT19</PUnitAbrvCh>
            <PosJobAbrvCh>BC-S</PosJobAbrvCh>
        </Record>
        <Record>
            <RscPayrollIDCh>12345</RscPayrollIDCh>
            <RscEmployeeIDCh>12345</RscEmployeeIDCh>
            <RscMasterNameCh>Smith, John A.</RscMasterNameCh>
            <InstitutionAbrvCh>SPL</InstitutionAbrvCh>
            <AgencyAbrvCh>SPFD</AgencyAbrvCh>
            <RegionAbrvCh>OPS</RegionAbrvCh>
            <StationAbrvCh>S15</StationAbrvCh>
            <PUnitAbrvCh>E15</PUnitAbrvCh>
            <PosJobAbrvCh>CAPT</PosJobAbrvCh>
        </Record>
        <Record>
            <RscPayrollIDCh>123456</RscPayrollIDCh>
            <RscEmployeeIDCh>123456</RscEmployeeIDCh>
            <RscMasterNameCh>Smith, Bob R.</RscMasterNameCh>
            <InstitutionAbrvCh>SPL</InstitutionAbrvCh>
            <AgencyAbrvCh>SPFD</AgencyAbrvCh>
            <RegionAbrvCh>OPS</RegionAbrvCh>
            <StationAbrvCh>S15</StationAbrvCh>
            <PUnitAbrvCh>E15</PUnitAbrvCh>
            <PosJobAbrvCh>ENG</PosJobAbrvCh>
        </Record>
    </Records>
</Data>

我想格式化XML,使其看起来像这样:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Data>
    <Date>2019-05-07-07:00</Date>
    <Headers></Headers>
    <Records>
        <Record>
            <StationAbrvCh>B19</StationAbrvCh>
                <RscMasterNameCh>Smith, Mike A.</RscMasterNameCh>
        </Record>
        <Record>
            <StationAbrvCh>S15</StationAbrvCh>
                <RscMasterNameCh>Smith, John A.</RscMasterNameCh>
                <RscMasterNameCh>Smith, Bob R.</RscMasterNameCh>
        </Record>
    </Records>

我希望我的名册列出当天分配给他们的车站下的每位机组人员。

2 个答案:

答案 0 :(得分:0)

使用 XSLT 2.0 非常简单。

在模板处理Records中,您应该使用for-each-group 选择Record元素并按StationAbrvCh进行分组。

在每个组中,您应该:

  • 生成StationAbrvCh元素,并用当前分组键填充 (也StationAbrvCh)。
  • 为当前组运行for-each循环,将以下内容复制到输出中: 当前RscMasterNameCh

该脚本还应包含身份模板

下面有一个示例脚本:

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

  <xsl:template match="Records">
    <xsl:copy>
      <xsl:for-each-group select="Record" group-by="StationAbrvCh">
        <xsl:copy>
          <StationAbrvCh><xsl:value-of select="current-grouping-key()"/></StationAbrvCh>
          <xsl:for-each select="current-group()">
            <xsl:sequence select="RscMasterNameCh"/>
          </xsl:for-each>
        </xsl:copy>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
  </xsl:template>
</xsl:stylesheet>

也许,要完全理解上述解决方案的每个细节, 您应该在网上搜索for-each-group的描述 以及相关功能(current-grouping-key()current-group)。

答案 1 :(得分:0)

如果您使用的是 XSLT 1.0 ,则使用 Muenchian分组是实现此目标的最佳方法,如下所示:

<?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" indent="yes" />
<xsl:key name="groups" match="/Data/Records/Record" use="StationAbrvCh" />

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>

<xsl:template match="/Data/Records">
    <xsl:copy>
        <xsl:for-each select="Record[generate-id() = generate-id(key('groups', StationAbrvCh)[1])]">
            <xsl:copy>
                <StationAbrvCh><xsl:value-of select="StationAbrvCh" /></StationAbrvCh>
                <xsl:for-each select="key('groups', StationAbrvCh)">
                    <RscMasterNameCh><xsl:value-of select="RscMasterNameCh" /></RscMasterNameCh>
                </xsl:for-each>
            </xsl:copy>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

在此处查看演示:https://xsltfiddle.liberty-development.net/pPzifpM