XSL 转换失败,我不明白为什么

XSL transform failing and i can't see why

作为编写 XSL 的新手,我在为我当前的项目调试 XSL 时遇到了问题。 EditX-XML 只是因为错误而导致转换失败,但没有说明它们在哪里。

感谢任何建议

来源XML:

<soa:Label xmlns:soa="urn:telestream.net:soa:core" identifier="ac7af7e5-a536-40ae-b7ca-93e62009c86a" name="Duration - Timecode to Frames" description="" instance="dc07adf4-79e4-4d33-b740-ece5bc0af991" signature="00000000-0000-0000-0000-000000000000">
<soa:Parameter type="timecode" identifier="82795f2a-5a2e-41ca-b1da-0c35a9c584e4" bindable="True" name="Duration Timecode" enabled="true" disableable="false" optionseditable="false" row="-1" column="-1" columnspan="1">00:15:52:10@25
<soa:Default>00:00:00:00@29.97</soa:Default>
<soa:IsRequired>false</soa:IsRequired>
</soa:Parameter>
<soa:Parameter type="int32" identifier="ca643595-6cbb-46b4-bf9b-da93c4348a4e" bindable="True" name="Duration Frames" enabled="true" disableable="false" optionseditable="false" row="-1" column="-1" columnspan="1">0
<soa:Default>0</soa:Default>
<soa:IsRequired>false</soa:IsRequired>
</soa:Parameter>
</soa:Label>

XSL:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soa="urn:telestream.net:soa:core" version="2.0">
<xsl:analyze-string select="/soa:Label/soa:Parameter[1]" regex="^(\d+):(\d+):(\d+):(\d+)@(\d+)$">
<xsl:matching-substring><xsl:variable name="hours" select="xs:integer(regex-group(1))"/>
<xsl:variable name="minutes" select="xs:integer(regex-group(2))"/>
<xsl:variable name="seconds" select="xs:integer(regex-group(3))"/>
<xsl:variable name="frames" select="xs:integer(regex-group(4))"/>
<xsl:variable name="fps" select="xs:integer(regex-group(5))"/>
<xsl:variable name="total-frames" select="$hours * 60 * 60 * $fps + $minutes * 60 * $fps + $seconds * $frames + $frames"/>
</xsl:matching-substring>
</xsl:analyze-string>
<xsl:template match="/">
<soa:Label identifier="5f01d03f-f867-4a57-92e0-19d239a3582d" name="Duration - Timecode to Frames pt2" description="" instance="dc07adf4-79e4-4d33-b740-ece5bc0af991" signature="00000000-0000-0000-0000-000000000000" xmlns:soa="urn:telestream.net:soa:core">
<soa:Parameter type="timecode" identifier="82795f2a-5a2e-41ca-b1da-0c35a9c584e4" bindable="True" name="Duration Timecode" enabled="true" disableable="false" optionseditable="false" row="-1" column="-1" columnspan="1">
<xsl:value-of select="/soa:Label/soa:Parameter[1]"/>
<soa:Default>00:00:00:00@29.97</soa:Default>
<soa:IsRequired>false</soa:IsRequired>
</soa:Parameter>
<soa:Parameter type="int32" identifier="ca643595-6cbb-46b4-bf9b-da93c4348a4e" bindable="True" name="Duration Frames" enabled="true" disableable="false" optionseditable="false" row="-1" column="-1" columnspan="1"><xsl:value-of select="$total-frames"/><soa:Default>0</soa:Default>
<soa:IsRequired>false</soa:IsRequired>
</soa:Parameter>
</soa:Label>
</xsl:template>
</xsl:stylesheet>

谢谢

如果您要在 http://xsltransform.net/ 测试 XSLT,您会发现 XSLT 有两个错误

  1. 元素 xsl:analyze-string 不允许成为
    的子元素 xsl:stylesheet
  2. 您在
    中定义了一个total-frames变量 这个 xsl:analyze-string 但这意味着它只在范围内 xsl:matching-substring 块,所以不能引用它 哪里.

具体细节见http://xsltransform.net/pPzifqj

您需要做的是移动 xsl:analyze-string,同时将 total-framesxsl:variable 声明包裹起来,以便以后可以在模板中使用该变量.

试试这个 XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:soa="urn:telestream.net:soa:core"
                version="2.0">
    <xsl:output method="xml" indent="yes" />

   <xsl:template match="/">
      <soa:Label identifier="5f01d03f-f867-4a57-92e0-19d239a3582d" name="Duration - Timecode to Frames pt2" description="" instance="dc07adf4-79e4-4d33-b740-ece5bc0af991" signature="00000000-0000-0000-0000-000000000000">
         <soa:Parameter type="timecode" identifier="82795f2a-5a2e-41ca-b1da-0c35a9c584e4" bindable="True" name="Duration Timecode" enabled="true" disableable="false" optionseditable="false" row="-1" column="-1" columnspan="1">
            <xsl:value-of select="normalize-space(/soa:Label/soa:Parameter[1]/text()[1])"/>
            <soa:Default>00:00:00:00@29.97</soa:Default>
            <soa:IsRequired>false</soa:IsRequired>
         </soa:Parameter>

        <xsl:variable name="total-frames">
            <xsl:analyze-string select="normalize-space(/soa:Label/soa:Parameter[1]/text()[1])"
                               regex="^(\d+):(\d+):(\d+):(\d+)@(\d+)$">
              <xsl:matching-substring>
                 <xsl:variable name="hours" select="xs:integer(regex-group(1))"/>
                 <xsl:variable name="minutes" select="xs:integer(regex-group(2))"/>
                 <xsl:variable name="seconds" select="xs:integer(regex-group(3))"/>
                 <xsl:variable name="frames" select="xs:integer(regex-group(4))"/>
                 <xsl:variable name="fps" select="xs:integer(regex-group(5))"/>

                 <xsl:value-of select="$hours * 60 * 60 * $fps + $minutes * 60 * $fps + $seconds * $frames + $frames"/>
              </xsl:matching-substring>
           </xsl:analyze-string>
       </xsl:variable> 

         <soa:Parameter type="int32" identifier="ca643595-6cbb-46b4-bf9b-da93c4348a4e" bindable="True" name="Duration Frames" enabled="true" disableable="false" optionseditable="false" row="-1" column="-1" columnspan="1">
            <xsl:value-of select="$total-frames"/>
            <soa:Default>0</soa:Default>
            <soa:IsRequired>false</soa:IsRequired>
         </soa:Parameter>
      </soa:Label>
   </xsl:template>
</xsl:stylesheet>

另请注意您选择的位置 soa:Parameter[1] 这也会包括文本中的所有换行符和白色-space 节点,因此您的正则表达式不会匹配。

话虽如此,看起来您正在尝试做的是在第一个参数的基础上将文本值附加到第二个参数。在这种情况下,您可能会受益于使用 XSLT 标识模板。

也试试这个 XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:soa="urn:telestream.net:soa:core"
                version="2.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:template match="soa:Parameter[2]">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:analyze-string select="normalize-space(/soa:Label/soa:Parameter[1]/text()[1])"
                               regex="^(\d+):(\d+):(\d+):(\d+)@(\d+)$">
              <xsl:matching-substring>
                 <xsl:variable name="hours" select="xs:integer(regex-group(1))"/>
                 <xsl:variable name="minutes" select="xs:integer(regex-group(2))"/>
                 <xsl:variable name="seconds" select="xs:integer(regex-group(3))"/>
                 <xsl:variable name="frames" select="xs:integer(regex-group(4))"/>
                 <xsl:variable name="fps" select="xs:integer(regex-group(5))"/>

                 <xsl:value-of select="$hours * 60 * 60 * $fps + $minutes * 60 * $fps + $seconds * $frames + $frames"/>
              </xsl:matching-substring>
           </xsl:analyze-string>
            <xsl:apply-templates select="*"/>
        </xsl:copy>
    </xsl:template>

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