【问题标题】:Condtional XML to XML transformation有条件的 XML 到 XML 的转换
【发布时间】:2016-07-21 07:03:23
【问题描述】:

我正在努力解决数据转换问题,非常感谢您的帮助和建议。

我想将一个相当大的 xml 文件转换成另一种 xml 格式。我的同事告诉我,使用 XSLT 可以解决我的问题,但乍一看,我发现 XSLT 无法执行我需要的条件格式。正如您从我的 xml 中看到的,我需要从开始和结束时间标签中描述的指定时间间隔派生多个时间序列点。

因此,我的问题是解决此类问题的最佳做法是什么?使用 XSLT 或使用其他技术可以轻松解决这个问题吗?或者这是编写自定义代码最好的处理方式?

期待您的回答。

最好的问候!

要转换的 XML:

<starttime>
    <datetime>201605130500</datetime>
    <qualifier>163</Qualifier>
</starttime>
<endtime>
    <datetime>201605150500</datetime>
    <qualifier>164</Qualifier>
</endtime>
<seriesPeriod>
    <quantityDetails>
        <quantity>8.0</quantity>
        <qualifier>135</qualifier>
    </quantityDetails>
    <datetimeDetails>
        <datetime>201605130500201605130600</datetime> <!-- This is a period to from 05:00 to 06:00 (from-to YYYYMMDDHHH-YYYYMMDDHHH) -->
        <qualifier>324</qualifier>
    </datetimeDetails>
</seriesPeriod>
<seriesPeriod>
    <quantityDetails>
        <quantity>-11</quantity>
        <qualifier>135</qualifier>
    </quantityDetails>
    <datetimeDetails>
        <dateTime>201605130600201605130700</dateTime>
        <qualifier>324</qualifier>
    </datetimeDetails>  
</seriesPeriod>
<!-- Continues with a total of 48 similar "seriesPeriod", one point for each hour in the timeinterval derived from starttime and endtime -->

改造后的预期结果:

<timeseries>
    <timeinterval>
        <start>2016-05-13T05:00Z</start>
        <end>2016-05-15T05:00Z</end>
    </timeinterval>
    <point>
        <position>1</position>
        <quantity>8</quantity>
    </point>
    <point>
        <position>2</position>
        <quantity>-11</quantity>
    </point>
    <!-- Continues with a total of 48 similar "points", one point for each hour in the timeinterval -->
</timeseries>

【问题讨论】:

  • XSLT 可能是完成这里任务的好工具,但您需要解释所需转换的逻辑。特别是,quantity 值在您的预期结果中来自哪里?谢谢
  • 对逻辑的解释 - 以及更全面(且格式正确!)的示例 - 将很有用。还要说明您是否可以使用 XSLT 2.0。
  • 请明确第一点“4”和第二点“-11”的数量是如何计算的。
  • 我的xml中的一个小错误,很抱歉造成误解。我已经更新了示例,以便在转换前和转换后的数量相等。这背后没有逻辑。

标签: xml xslt xml-parsing transformation


【解决方案1】:

您的问题并不完全清楚。尤其是关于“条件格式”的部分——我在你的描述中没有看到任何条件。

FWIW,以下样式表:

XSLT 1.0

<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="/root">
    <timeseries>
        <timeinterval>
            <start>
                <xsl:call-template name="format-as-date">
                    <xsl:with-param name="string" select="starttime/datetime"/>
                </xsl:call-template>
            </start>
            <end>
                <xsl:call-template name="format-as-date">
                    <xsl:with-param name="string" select="endtime/datetime"/>
                </xsl:call-template>
            </end>
        </timeinterval>
        <xsl:for-each select="seriesPeriod">
            <point>
                <position>
                    <xsl:value-of select="position()"/>
                </position>
                <quantity>
                    <xsl:value-of select="number(quantityDetails/quantity)"/>
                </quantity>
            </point>
        </xsl:for-each>
    </timeseries>
</xsl:template>

<xsl:template name="format-as-date">
    <xsl:param name="string"/>
    <xsl:value-of select="substring($string, 1, 4)"/>
    <xsl:text>-</xsl:text>
    <xsl:value-of select="substring($string, 5, 2)"/>
    <xsl:text>-</xsl:text>
    <xsl:value-of select="substring($string, 7, 2)"/>
    <xsl:text>T</xsl:text>
    <xsl:value-of select="substring($string, 9, 2)"/>
    <xsl:text>:</xsl:text>
    <xsl:value-of select="substring($string, 11, 2)"/>
    <xsl:text>Z</xsl:text>
</xsl:template>

</xsl:stylesheet>

当应用于以下格式正确的 (!) 输入时:

XML

<root>
  <starttime>
    <datetime>201605130500</datetime>
    <qualifier>163</qualifier>
  </starttime>
  <endtime>
    <datetime>201605150500</datetime>
    <qualifier>164</qualifier>
  </endtime>  
  <seriesPeriod>
    <quantityDetails>
      <quantity>8.0</quantity>
      <qualifier>135</qualifier>
    </quantityDetails>
    <datetimeDetails>
      <datetime>201605130500201605130600</datetime>
      <qualifier>324</qualifier>
    </datetimeDetails>
  </seriesPeriod>
  <seriesPeriod>
    <quantityDetails>
      <quantity>-11</quantity>
      <qualifier>135</qualifier>
    </quantityDetails>
    <datetimeDetails>
      <dateTime>201605130600201605130700</dateTime>
      <qualifier>324</qualifier>
    </datetimeDetails>
  </seriesPeriod>
</root>

将返回:

结果

<?xml version="1.0" encoding="UTF-8"?>
<timeseries>
   <timeinterval>
      <start>2016-05-13T05:00Z</start>
      <end>2016-05-15T05:00Z</end>
   </timeinterval>
   <point>
      <position>1</position>
      <quantity>8</quantity>
   </point>
   <point>
      <position>2</position>
      <quantity>-11</quantity>
   </point>
</timeseries>

这与您的预期结果相同 - 无论是设计还是巧合。

【讨论】:

  • 非常感谢迈克尔!我对 XSLT 很陌生,所以这对我的学习有很大帮助。我所说的条件格式的意思是我认为我必须从开始时间和结束时间推导出位置编号,因为我不知道'value-of select="position()'。
  • "我认为我必须从开始时间和结束时间推导出位置编号" 这将是一个“有趣”的问题......
猜你喜欢
  • 2017-10-14
  • 2019-01-23
  • 1970-01-01
  • 1970-01-01
  • 2020-07-28
  • 2017-06-07
  • 2020-08-28
  • 2017-06-02
  • 1970-01-01
相关资源
最近更新 更多