Make new node using sub-node sub-string

家住魔仙堡 提交于 2019-12-25 00:32:28

问题


I have an xml document that looks like this:

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

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

I want it to be this:

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

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

I've tried this.

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

but only get the first of the file ext. e.g. if jpeg is first, I would get for both of the nodes. Could someone offer expertise advice on why this is not working.

BTW, I also tried this but same thing happened:

<xsl:template match="//xmlns:oldNode[contains(//root:ele1, '.jpeg')]">
  <xsl:element name="JPEG">
      <xsl:apply-templates select="@*|node()"/>
  </xsl:element>
</xsl:template>

<xsl:template match="//xmlns:oldNode[contains(//root:ele1, '.tiff')]">
  <xsl:element name="TIFF">
      <xsl:apply-templates select="@*|node()"/>
  </xsl:element>
</xsl:template>

回答1:


<xsl:template match="oldNode">
    <xsl:choose>
        <xsl:when test="contains(ele1,'.jpeg')">
            <xsl:element name="JPEG">
                <xsl:apply-templates select="@*|node()"/>
            </xsl:element>
        </xsl:when>
        <xsl:when test="contains(ele1,'.tiff')">
            <xsl:element name="TIFF">
                <xsl:apply-templates select="@*|node()"/>
            </xsl:element>
        </xsl:when>
    </xsl:choose>
</xsl:template>



回答2:


The first problem is with your matching template

 <xsl:template match="//xmlns:oldNode[contains(//xmlsns:oldNode/root:ele1, '.')]">

In particular, with the contains element you probably don't want the //oldNode at the front, as this will start looking for the first oldNode relative to the root element. What you really want is to look for the ele1 element relative to the element you have currently matched

<xsl:template match="//oldNode[contains(ele1, '.')]">

(I am not sure if you mean oldNode or oldEle by the way. I am also not sure where your namespaces fit in, so I have not shown them here).

The second problem is with the xsl:element, as you are doing a similar thing here

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

Because of the // in the substring-after, it will pick up the first ele1 relative to the root element of the XML, and not the one relative to your current element. You probably need to do this

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

Try this template instead

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

Similarly, for you second set of templates, you should be doing something like this

<xsl:template match="//oldNode[contains(ele1, '.jpeg')]"> 



回答3:


Here is the same answer as to your previous question -- this solves completely the old and the current problem and no recursion is used:

<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"/>

     <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>

When this transformation is applied on the provided XML document, the wanted, correct result is produced:

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

Explanation:

In this transformation we are using the following XPath 1.0 expression to implement the standard XPath 2.0 ends-with($t, $suf) function:

$suf = substring($t, string-length($t) - string-length($suf) +1)


来源:https://stackoverflow.com/questions/10903013/make-new-node-using-sub-node-sub-string

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!