我正在尝试编写一个XSLT样式表,它从XML表单中的任何时间戳中删除毫秒。下面的示例XML只是一个示例,可以想象信封中包含任意数量的时间戳。所以我想我需要模式匹配时间戳然后转换它。我可以使用XSLT 2.0原始消息如下:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
</soap:Header>
<soap:Body>
<Staging_Submit_Service xmlns="com.xxx">
<u_From_Partner__c>Our Partner</u_From_Partner__c>
<u_To_Partner__c>Us</u_To_Partner__c>
<u_Partner_CI__c/>
<u_Partner_ID__c>10051</u_Partner_ID__c>
<u_Partner_Name__c>ROSEVILLE</u_Partner_Name__c>
<u_Partner_Reported_Date__c>2016-07-26T17:38:28.746134Z</u_Partner_Reported_Date__c>
<u_Partner_Status_Reason__c>Failure in System</u_Partner_Status_Reason__c>
<u_Partner_Submit_Date__c>2016-07-25T18:11:23.5443Z</u_Partner_Submit_Date__c>
<u_Partner_Priority__c>Low</u_Partner_Priority__c>
<u_Partner_Service_Type>Event</u_Partner_Service_Type>
</Staging_Submit_Service>
</soap:Body>
</soap:Envelope>
我生成的xml需要看起来像:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
</soap:Header><soap:Body>
<Staging_Submit_Service xmlns="com.xxx">
<u_From_Partner__c>Our Partner</u_From_Partner__c>
<u_To_Partner__c>Us</u_To_Partner__c>
<u_Partner_CI__c/>
<u_Partner_ID__c>10051</u_Partner_ID__c>
<u_Partner_Name__c>ROSEVILLE</u_Partner_Name__c>
<u_Partner_Reported_Date__c>2016-07-26T17:38:28Z</u_Partner_Reported_Date__c>
<u_Partner_Status_Reason__c>Failure in System</u_Partner_Status_Reason__c>
<u_Partner_Submit_Date__c>2016-07-25T18:11:23Z</u_Partner_Submit_Date__c>
<u_Partner_Priority__c>Low</u_Partner_Priority__c>
<u_Partner_Service_Type>Event</u_Partner_Service_Type>
</Staging_Submit_Service>
</soap:Body>
</soap:Envelope>
注意时间戳。我开始走这条路,但它似乎没有让我到达我需要的地方。
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="java:com.verizon.webservices.adapter.clecclient">
<xsl:output method="xml" indent="no" version="1.0" encoding="UTF-8" omit-xml-declaration="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()"
<xsl:copy>
<xsl:value-of select="." />
<xsl:value-of select='matches(.,".*[0-9]\{4\}-[0-9]\{2\}.*:[0-9]\{2\}*")'/>
<xsl:value-of select='replace(., "s/.*[0-9]\{4\}-[0-9]\{2\}.*:[0-9]\{2\}\(\.[0-9]*\).*/\1","")'/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我真的只是模糊地熟悉XSLT,这个特殊问题需要我使用它。
答案 0 :(得分:1)
从评论看来,您似乎只能使用XSLT 1.0解决方案。
这是一个:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:df="com.xxx">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="df:u_Partner_Reported_Date__c/text()
|df:u_Partner_Submit_Date__c/text()">
<xsl:value-of select="concat(substring-before(.,'.'), 'Z')"/>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
</soap:Header>
<soap:Body>
<Staging_Submit_Service xmlns="com.xxx">
<u_From_Partner__c>Our Partner</u_From_Partner__c>
<u_To_Partner__c>Us</u_To_Partner__c>
<u_Partner_CI__c/>
<u_Partner_ID__c>10051</u_Partner_ID__c>
<u_Partner_Name__c>ROSEVILLE</u_Partner_Name__c>
<u_Partner_Reported_Date__c>2016-07-26T17:38:28.746134Z</u_Partner_Reported_Date__c>
<u_Partner_Status_Reason__c>Failure in System</u_Partner_Status_Reason__c>
<u_Partner_Submit_Date__c>2016-07-25T18:11:23.5443Z</u_Partner_Submit_Date__c>
<u_Partner_Priority__c>Low</u_Partner_Priority__c>
<u_Partner_Service_Type>Event</u_Partner_Service_Type>
</Staging_Submit_Service>
</soap:Body>
</soap:Envelope>
产生了想要的正确结果:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
</soap:Header>
<soap:Body>
<Staging_Submit_Service xmlns="com.xxx">
<u_From_Partner__c>Our Partner</u_From_Partner__c>
<u_To_Partner__c>Us</u_To_Partner__c>
<u_Partner_CI__c/>
<u_Partner_ID__c>10051</u_Partner_ID__c>
<u_Partner_Name__c>ROSEVILLE</u_Partner_Name__c>
<u_Partner_Reported_Date__c>2016-07-26T17:38:28Z</u_Partner_Reported_Date__c>
<u_Partner_Status_Reason__c>Failure in System</u_Partner_Status_Reason__c>
<u_Partner_Submit_Date__c>2016-07-25T18:11:23Z</u_Partner_Submit_Date__c>
<u_Partner_Priority__c>Low</u_Partner_Priority__c>
<u_Partner_Service_Type>Event</u_Partner_Service_Type>
</Staging_Submit_Service>
</soap:Body>
</soap:Envelope>
答案 1 :(得分:0)
尝试
<xsl:template match="*[not(*) and . castable as xs:dateTime]">
<xsl:copy>
<xsl:value-of select="format-dateTime(., '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01]')"/>
</xsl:copy>
</xsl:template>
加上你的第一个模板。
所以完整的样式表是
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(*) and . castable as xs:dateTime]">
<xsl:copy>
<xsl:value-of select="format-dateTime(., '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01]')"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
实际上上面似乎没有保留任何时区后缀并确保它输出为Z
如果是UTC有点棘手,但我想如果你做value-of
<xsl:value-of select="if (timezone-from-dateTime(.) eq xs:dayTimeDuration('PT0H')) then format-dateTime(., '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01]Z') else format-dateTime(., '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01][Z]')"/>
然后它运作正常。
有关时区Z
的问题似乎已在https://www.w3.org/TR/xpath-functions-31/#rules-for-datetime-formatting中解决以允许
<xsl:value-of select="format-dateTime(., '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01][Z00:00t]')"/>
但我没有测试它是否适用于XmlPrime或Saxon以外的处理器。
以下对我来说,在Oxygen中使用Xalan,只需在输入样本中使用dateTimes识别两个元素,然后重新格式化它们以删除秒的小数:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:date="http://exslt.org/dates-and-times"
exclude-result-prefixes="xs date" version="1.0">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(*) and string-length() > 19 and date:date() != '']">
<xsl:copy>
<xsl:value-of select="date:format-date(date:date(.), "yyyy-MM-dd'T'HH:mm:ssZ")"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
但是,创建的输出日期不同,输入<u_Partner_Reported_Date__c>2016-07-26T17:38:28.746134Z</u_Partner_Reported_Date__c>
显示为<u_Partner_Reported_Date__c>2016-07-25T22:00:00+0000</u_Partner_Reported_Date__c>
,因此日期解析或格式设置已损坏。