【问题标题】:XSLT transformation not applied to complex XMLXSLT 转换不适用于复杂的 XML
【发布时间】:2020-09-08 17:58:26
【问题描述】:

我有一个自定义 XML,如下所示

<AllValues xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <content>
        <data>
            <item>
                <value xsi:type="DATETIME">
                    <value>2020-12-31T09:30:00+00:00</value>
                </value>
            </item>
        </data>
    </content>
</AllValues>

我想从定义的样式表中提取 2020-12-31T09:30:00+00:00September 24th, 2020 09:30 。但是,在这种情况下,样式表似乎无法识别元素。

我的样式表(改编自here)定义如下

<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:strip-space elements="*"/>
    <xsl:template match="/">
        <output>
            <xsl:variable name="month" select="substring(date, 6, 2)"/>
            <xsl:choose>
                <xsl:when test="$month=1">January</xsl:when>
                <xsl:when test="$month=2">February</xsl:when>
                <xsl:when test="$month=3">March</xsl:when>
                <xsl:when test="$month=4">April</xsl:when>
                <xsl:when test="$month=5">May</xsl:when>
                <xsl:when test="$month=6">June</xsl:when>
                <xsl:when test="$month=7">July</xsl:when>
                <xsl:when test="$month=8">August</xsl:when>
                <xsl:when test="$month=9">September</xsl:when>
                <xsl:when test="$month=10">October</xsl:when>
                <xsl:when test="$month=11">November</xsl:when>
                <xsl:when test="$month=12">December</xsl:when>
            </xsl:choose>
            <xsl:text> </xsl:text>
            <xsl:variable name="day" select="number(substring(date, 9, 2))"/>
            <xsl:value-of select="$day"/>
            <xsl:choose>
                <xsl:when test="$day=1 or $day=21 or $day=31">st</xsl:when>
                <xsl:when test="$day=2 or $day=22">nd</xsl:when>
                <xsl:otherwise>th</xsl:otherwise>
            </xsl:choose>
            <xsl:text>, </xsl:text>
            <xsl:value-of select="substring(date, 1, 4)"/>
            <xsl:text> </xsl:text>
            <xsl:value-of select="substring(date, 12, 5)"/>
        </output>
    </xsl:template>
</xsl:stylesheet>

一个非常基本的场景似乎可以正常工作,但我无法在此处转换复杂的 xml。这是它工作的基本情况的实现https://xsltfiddle.liberty-development.net/bEzknt7/1

非常感谢您的帮助

【问题讨论】:

    标签: xml xslt transformation


    【解决方案1】:

    您只是没有匹配 XSLT 中的正确节点。
    将表达式中的 date 节点更改为 . 并在模板中设置正确的上下文节点:

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:template match="//*[@xsi:type='DATETIME']/value">
            <xsl:element name="output">
                <xsl:variable name="month" select="substring(., 6, 2)"/>
                <xsl:choose>
                    <xsl:when test="$month=1">January</xsl:when>
                    <xsl:when test="$month=2">February</xsl:when>
                    <xsl:when test="$month=3">March</xsl:when>
                    <xsl:when test="$month=4">April</xsl:when>
                    <xsl:when test="$month=5">May</xsl:when>
                    <xsl:when test="$month=6">June</xsl:when>
                    <xsl:when test="$month=7">July</xsl:when>
                    <xsl:when test="$month=8">August</xsl:when>
                    <xsl:when test="$month=9">September</xsl:when>
                    <xsl:when test="$month=10">October</xsl:when>
                    <xsl:when test="$month=11">November</xsl:when>
                    <xsl:when test="$month=12">December</xsl:when>
                </xsl:choose>
                <xsl:text> </xsl:text>
                <xsl:variable name="day" select="number(substring(., 9, 2))"/>
                <xsl:value-of select="$day"/>
                <xsl:choose>
                    <xsl:when test="$day=1 or $day=21 or $day=31">st</xsl:when>
                    <xsl:when test="$day=2 or $day=22">nd</xsl:when>
                    <xsl:otherwise>th</xsl:otherwise>
                </xsl:choose>
                <xsl:text>, </xsl:text>
                <xsl:value-of select="substring(., 1, 4)"/>
                <xsl:text> </xsl:text>
                <xsl:value-of select="substring(., 12, 5)"/>
            </xsl:element>
        </xsl:template>
    </xsl:stylesheet>
    

    它的输出是:

    <output>December 31st, 2020 09:30</output>
    

    这适用于您的 MCVE,适用于所有 xsi:type 属性等于 DATETIME 的元素。

    【讨论】:

    • 嘿,谢谢你的回答,无论如何我可以将此样式表应用于 xsi type = DateTime 的所有元素?
    • @devz:我根据新要求更新了我的答案。
    【解决方案2】:

    如果您的输入有多个需要转换的dateTime 值,则定义一个命名模板以用作遇到dateTime 值时可以调用的函数。例如:

    XML

    <AllValues xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <content>
            <data>
               <item>
                    <value xsi:type="STRING">
                        <value>Alpha</value>
                    </value>
                </item>
                <item>
                    <value xsi:type="DATETIME">
                        <value>2019-08-02T15:05:00+00:00</value>
                    </value>
                </item>
            </data>
            <data>
               <item>
                    <value xsi:type="STRING">
                        <value>Bravo</value>
                    </value>
                </item>
                <item>
                    <value xsi:type="DATETIME">
                        <value>2020-12-31T09:30:00+00:00</value>
                    </value>
                </item>
            </data>
        </content>
    </AllValues>
    

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <!-- identity transform -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="value[@xsi:type='DATETIME']/value">
        <xsl:copy>
            <xsl:call-template name="convert-dateTime">
                <xsl:with-param name="dateTime" select="."/>
            </xsl:call-template>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template name="convert-dateTime">
        <xsl:param name="dateTime"/>
        <xsl:variable name="month" select="substring($dateTime, 6, 2)"/>
        <xsl:choose>
            <xsl:when test="$month=1">January</xsl:when>
            <xsl:when test="$month=2">February</xsl:when>
            <xsl:when test="$month=3">March</xsl:when>
            <xsl:when test="$month=4">April</xsl:when>
            <xsl:when test="$month=5">May</xsl:when>
            <xsl:when test="$month=6">June</xsl:when>
            <xsl:when test="$month=7">July</xsl:when>
            <xsl:when test="$month=8">August</xsl:when>
            <xsl:when test="$month=9">September</xsl:when>
            <xsl:when test="$month=10">October</xsl:when>
            <xsl:when test="$month=11">November</xsl:when>
            <xsl:when test="$month=12">December</xsl:when>
        </xsl:choose>
        <xsl:text> </xsl:text>
        <xsl:variable name="day" select="number(substring($dateTime, 9, 2))"/>
        <xsl:value-of select="$day"/>
        <xsl:choose>
            <xsl:when test="$day=1 or $day=21 or $day=31">st</xsl:when>
            <xsl:when test="$day=2 or $day=22">nd</xsl:when>
            <xsl:otherwise>th</xsl:otherwise>
        </xsl:choose>
        <xsl:text>, </xsl:text>
        <xsl:value-of select="substring($dateTime, 1, 4)"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="substring($dateTime, 12, 5)"/>
    </xsl:template>
    
    </xsl:stylesheet>
    

    结果

    <?xml version="1.0" encoding="UTF-8"?>
    <AllValues xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <content>
        <data>
          <item>
            <value xsi:type="STRING">
              <value>Alpha</value>
            </value>
          </item>
          <item>
            <value xsi:type="DATETIME">
              <value>August 2nd, 2019 15:05</value>
            </value>
          </item>
        </data>
        <data>
          <item>
            <value xsi:type="STRING">
              <value>Bravo</value>
            </value>
          </item>
          <item>
            <value xsi:type="DATETIME">
              <value>December 31st, 2020 09:30</value>
            </value>
          </item>
        </data>
      </content>
    </AllValues>
    

    【讨论】:

      猜你喜欢
      • 2015-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-22
      • 2020-06-10
      • 1970-01-01
      • 2013-11-14
      • 1970-01-01
      相关资源
      最近更新 更多