我正在嘗試通過更改 2 個日期欄位來轉換一個 xml。
這是我的源 XML:
<?xml version="1.0" encoding="UTF-8"?>
<Publication_MarketDocument xmlns="urn:iec62325.351:tc57wg16:451-3:publicationdocument:7:0">
<period.timeInterval>
<start>2022-09-27T22:00Z</start>
<end>2022-09-29T22:00Z</end>
</period.timeInterval>
<TimeSeries>
<Period>
<timeInterval>
<start>2022-09-27T22:00Z</start>
<end>2022-09-28T22:00Z</end>
</timeInterval>
<resolution>PT60M</resolution>
<Point>
<position>1</position>
<price.amount>323.70</price.amount>
</Point>
<Point>
<position>2</position>
<price.amount>309.91</price.amount>
</Point>
</Period>
</TimeSeries>
</Publication_MarketDocument>
我希望所有開始節點都使用當前的日期時間,而結束節點則在一天后。所以我寫了以下 XSLT:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath-default-namespace="urn:iec62325.351:tc57wg16:451-3:publicationdocument:7:0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="dateNow" select="fn:format-dateTime(fn:current-dateTime(), '[Y]-[M]-[D]T[H]:[m]Z')"/>
<xsl:variable name="dateTomorrow" select="fn:format-dateTime(fn:current-dateTime() xs:dayTimeDuration('P1D'), '[Y]-[M]-[D]T[H]:[m]Z')"/>
<xsl:template match="start/text()">
<xsl:value-of select="$dateNow"/>
</xsl:template>
<xsl:template match="end/text()">
<xsl:value-of select="$dateTomorrow"/>
</xsl:template>
</xsl:stylesheet>
(編輯后)我首先對命名空間感到困惑,但按照評論建議定義默認命名空間允許此轉換運行。
但是,它是 xslt 2.0,因此 xslt 1.0 處理器不支持。例如,Visual Studio 2022 提供 xml 除錯,但仍然不支持 xslt 2.0。由于我的目標環境是基于 Linux 的,我發現最標準的解決方案是使用 Saxon:java net.sf.saxon.Transform -o:/mnt/d/tmp/output.xml -s:mock.xml -xsl:變換.xslt
這會靜默運行,最終得到正確的結果。但是對于自動化測驗系統的部署來說,使用 jre 是相當繁重的。僅使用 XSLT 1.0 就可以這樣做嗎?如此處所示,時移似乎相當復雜
uj5u.com熱心網友回復:
由于這個問題專門針對xsltproc,值得指出的是,libxslt處理器使用的處理器xsltproc支持一些擴展功能,可以解決問題,而無需呼叫應用程式完成所有作業:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:entsoe="urn:iec62325.351:tc57wg16:451-3:publicationdocument:7:0"
xmlns:date="http://exslt.org/dates-and-times"
exclude-result-prefixes="entsoe date">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="today" select="date:date-time()" />
<xsl:variable name="tomorrow" select="date:add($today, 'P1D')" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="entsoe:start/text()">
<xsl:value-of select="$today" />
</xsl:template>
<xsl:template match="entsoe:end/text()">
<xsl:value-of select="$tomorrow" />
</xsl:template>
</xsl:stylesheet>
uj5u.com熱心網友回復:
在 Linux 下使用 xsltproc,在這個問題之后,使用字串引數有一個更簡單的選擇。不是通過 xsl 進行 dateTime 處理(這在 XSLT 1.0 中不是開箱即用的),而是使用 shell 下的 date 工具來處理!所以我最終得到了以下 xslt
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:entsoe="urn:iec62325.351:tc57wg16:451-3:publicationdocument:7:0" exclude-result-prefixes="entsoe">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="entsoe:start/text()">
<xsl:value-of select="$dateNow"/>
</xsl:template>
<xsl:template match="entsoe:end/text()">
<xsl:value-of select="$dateTomorrow"/>
</xsl:template>
</xsl:stylesheet>
與來自 Linux 下的 sh 腳本的以下呼叫一起使用:
xsltproc --stringparam dateNow $(date -u %Y-%m-%dT%H:%MZ) --stringparam dateTomorrow $(date -u -d " 1 days" %Y-%m-%dT%H:%MZ) -o /mnt/d/tmp/output.xml ./transform.xslt ./mock-src.xml
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/517701.html
標籤:xmlxslt
