1

我有以下 XML 1.0 代码

<oldEle userlabel="label1">
    <ele1>%02d.jpeg</ele1>
</oldEle>

<oldEle userlabel="label2">
    <ele1>%02d.tiff</ele1>
</oldEle>

我想使用 xsl v1.0 将每个 oldEle 的 oldEle 更改为 jpeg 和 tiff。本质上我希望 xsl 这样做:

<JPEG userlabel="label1">
    <ele1>%02d.jpeg</ele1>
</JPEG>

<TIFF userlabel="label2">
    <ele1>%02d.tiff</ele1>
</TIFF>

我尝试了以下方法,但它不起作用:

<xsl:template match="/oldEle">
    <xsl:for-each select="/oldEle">
    <xsl:if test="contains(/oldEle/ele1,'jpeg')">
        <JPEG>
          <xsl:apply-templates select="@*|node()"/>
        </JPEG>      
    </xsl:if>      
    </xsl:for-each>
</xsl:template>

谢谢!

4

2 回答 2

0

如果您可以保证ele1元素将只包含一个句号,您可以使用 xpath 函数substring-after提取文件扩展名,然后使用xsl:element函数创建一个具有该名称的新元素

<xsl:element name="{substring-after(ele1, '.')}">

但是需要额外的复杂性,因为您也需要将其转换为大写,而在 XSLT1.0 中,这将通过繁琐的translate函数来实现

<xsl:element 
   name="{translate(
     substring-after(ele1, '.'), 
     'abcdefghijklmnopqrstuvwxyz', 
     'ABCDEFGHIJKLMNOPQRSTUVWXYZ')}">

另一件需要注意的事情是,您正在匹配/oldEle这意味着oldEle是您的 XML 的根元素。由于您在格式良好的 XML 中只能有一个根元素,因此这可能不是您想要的。

这是完整的 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="oldEle[contains(ele1, '.')]">
      <xsl:element name="{translate(substring-after(ele1, '.'), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')}">
         <xsl:apply-templates select="@*|node()"/>
      </xsl:element>
   </xsl:template>

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

应用于以下 XML 时

<root>
   <oldEle userlabel="label1">
      <ele1>%02d.jpeg</ele1>
   </oldEle>
   <oldEle userlabel="label2">
      <ele1>%02d.tiff</ele1>
   </oldEle>
</root>

以下是输出

<root>
   <JPEG userlabel="label1">
      <ele1>%02d.jpeg</ele1>
   </JPEG>
   <TIFF userlabel="label2">
      <ele1>%02d.tiff</ele1>
   </TIFF>
</root>

但是,如果ele1包含多个句号,XSLT 将会失败。例如,考虑以下 XML

<root>
   <oldEle userlabel="label1">
      <ele1>test.image1.jpeg</ele1>
   </oldEle>
   <oldEle userlabel="label2">
      <ele1>test.image2.tiff</ele1>
   </oldEle>
</root>

在这种情况下,在 XSLT1.0 中,您可能需要一个递归命名模板来提取文件扩展名。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="oldEle[contains(ele1, '.')]">
      <xsl:variable name="extension">
         <xsl:call-template name="getExtension">
            <xsl:with-param name="text" select="ele1"/>
         </xsl:call-template>
      </xsl:variable>

      <xsl:element name="{translate($extension, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')}">
         <xsl:apply-templates select="@*|node()"/>
      </xsl:element>
   </xsl:template>

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

   <xsl:template name="getExtension">
      <xsl:param name="text"/>
      <xsl:param name="delimiter" select="'.'"/>
      <xsl:choose>
         <xsl:when test="contains($text, $delimiter)">
            <xsl:call-template name="getExtension">
               <xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
               <xsl:with-param name="delimiter" select="$delimiter"/>
            </xsl:call-template>
         </xsl:when>
         <xsl:otherwise>
            <xsl:value-of select="$text"/>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>
</xsl:stylesheet>

这也会产生相同的输出。

于 2012-06-05T08:30:19.383 回答
0

这是一个非递归且更高效的 XSLT 1.0 解决方案,它可以成功地与任意数量的图像格式扩展一起工作,假设它们是静态已知的

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <my:suffixes>
  <s>jpeg</s><s>JPEG</s>
  <s>tiff</s><s>TIFF</s>
  <s>giv</s><s>GIV</s>
  <s>png</s><s>PNG</s>
 </my:suffixes>

 <xsl:variable name="vSufs" select="document('')/*/my:suffixes/s"/>

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

 <xsl:template match="*">
   <xsl:variable name="vSufFound" select=
    "$vSufs[position() mod 2 = 1]
         [substring(translate(current()/ele1, ., ''),
                    string-length(translate(current()/ele1, ., ''))
                    )
         =
          '.'
         ]"/>
   <xsl:choose>
     <xsl:when test="not($vSufFound)">
      <xsl:call-template name="identity"/>
     </xsl:when>
     <xsl:otherwise>
       <xsl:element name="{$vSufFound/following-sibling::s[1]}">
         <xsl:apply-templates select="node()|@*"/>
       </xsl:element>
     </xsl:otherwise>
   </xsl:choose>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时

<t>
    <oldEle userlabel="label1">
        <ele1>%02d.jpeg</ele1>
    </oldEle>
    <oldEle userlabel="label2">
        <ele1>%02d.tiff</ele1>
    </oldEle>
</t>

产生了想要的正确结果:

<t>
   <JPEG userlabel="label1">
      <ele1>%02d.jpeg</ele1>
   </JPEG>
   <TIFF userlabel="label2">
      <ele1>%02d.tiff</ele1>
   </TIFF>
</t>

当应用于以下 XML 文档时(其中的字符串值中存在多个点字符ele

<root>
    <oldEle userlabel="label1">
        <ele1>test.image1.jpeg</ele1>
    </oldEle>
    <oldEle userlabel="label2">
        <ele1>test.image2.tiff</ele1>
    </oldEle>
</root>

再次产生正确的结果:

<root>
   <JPEG userlabel="label1">
      <ele1>test.image1.jpeg</ele1>
   </JPEG>
   <TIFF userlabel="label2">
      <ele1>test.image2.tiff</ele1>
   </TIFF>
</root>

说明

在此转换中,我们使用以下 XPath 1.0 表达式来实现标准 XPath 2.0ends-with($t, $suf)函数:

$suf = substring($t, string-length($t) - string-length($suf) +1)
于 2012-06-05T12:20:34.720 回答