XSL转换为使用匹配的id从第一个前一个项复制属性

时间:2012-08-10 02:08:49

标签: xml xslt

嗨这是对此处发布的上一个问题的改编。

XSLT - Find element values from first preceding item with matching name id - Using conditionals?

我有一个看起来像下面的XML。

我想创建一个xsl转换,在帖子的底部生成理想的xml。

请注意,在提供的XML中,如果Image节点被多次使用(由其文件ID定义),则其后续子元素不存在。例如,其文件id与第一图像节点相同的第三图像节点不包含子属性和后续值。我想把它们重新加入。

我有下面的当前示例xsl基本上工作但我想在样式表中添加条件评估,其中说: 用英语讲: 如果'key'元素不存在,则找到第一个匹配的'file id'并使用这些元素中的值。这同样适用于'string和'reel'元素。 (在文件节点中弹出的任何其他任何其他内容。

结果将根据匹配文件ID的第一个实例为空文件节点填充所有相关数据。

为我糟糕的描述道歉。

非常感谢任何帮助。

XML:

<?xml version="1.0"?>
<xmeml>
<boxset>
<stream>
    <track>
        <image>
            <start>0</start>
            <end>90</end>
            <file id="abcde">
                <key>95</key>
                <string>1023</string>
                <time>
                    <reel>142</reel>
                </time>
            </file>
        </image>
        <image>
            <start>90</start>
            <end>120</end>
            <file id="bcdef">
                <key>55</key>
                <string>1023</string>
                <time>
                    <reel>64</reel>
                </time>
            </file>
        </image>
    </track>
    <track>
        <image>
            <start>120</start>
            <end>130</end>
            <file id="abcde"/>
        </image>
        <image>
            <start>130</start>
            <end>180</end>
            <file id="cdefg">
                <key>92</key>
                <string>1023</string>
                <time>
                    <reel>194</reel>
                </time>
            </file>
        </image>    
    </track>
</stream>
</boxset>
</xmeml>

XSLT:标准身份转换

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


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

</xsl:stylesheet>

如果要填充XML,我们希望看到它看起来像这样。

理想的XML:

<?xml version="1.0"?>
<xmeml>
<boxset>
<stream>
    <track>
        <image>
            <start>0</start>
            <end>90</end>
            <file id="abcde">
                <key>95</key>
                <string>1023</string>
                <time>
                    <reel>142</reel>
                </time>
            </file>
        </image>
        <image>
            <start>90</start>
            <end>120</end>
            <file id="bcdef">
                <key>55</key>
                <string>1023</string>
                <time>
                    <reel>64</reel>
                </time>
            </file>
        </image>
    </track>
    <track>
        <image>
            <start>120</start>
            <end>130</end>
<!-- ideal data for repeated file "abcde" -->
            <file id="abcde">
                <key>95</key>
                <string>1023</string>
                <time>
                    <reel>142</reel>
                </time>
            </file>
<!-- end ideal repeated data -->
        </image>
        <image>
            <start>130</start>
            <end>180</end>
            <file id="cdefg">
                <key>92</key>
                <string>1023</string>
                <time>
                    <reel>194</reel>
                </time>
            </file>
        </image>    
    </track>
</stream>
</boxset>
</xmeml>

2 个答案:

答案 0 :(得分:1)

此转化

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

 <xsl:key name="kImageById" match="image" use="file/@id"/>

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

 <xsl:template match=
  "image[not(generate-id()
            =generate-id(key('kImageById',file/@id)[1])
            )]">
  <xsl:copy>
   <xsl:apply-templates select="@*|start|end"/>
   <xsl:apply-templates select=
   "key('kImageById',file/@id)[1]/*[not(self::start or self::end)]"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<xmeml>
    <boxset>
        <stream>
            <track>
                <image>
                    <start>0</start>
                    <end>90</end>
                    <file id="abcde">
                        <key>95</key>
                        <string>1023</string>
                        <time>
                            <reel>142</reel>
                        </time>
                    </file>
                </image>
                <image>
                    <start>90</start>
                    <end>120</end>
                    <file id="bcdef">
                        <key>55</key>
                        <string>1023</string>
                        <time>
                            <reel>64</reel>
                        </time>
                    </file>
                </image>
            </track>
            <track>
                <image>
                    <start>120</start>
                    <end>130</end>
                    <file id="abcde"/>
                </image>
                <image>
                    <start>130</start>
                    <end>180</end>
                    <file id="cdefg">
                        <key>92</key>
                        <string>1023</string>
                        <time>
                            <reel>194</reel>
                        </time>
                    </file>
                </image>
            </track>
        </stream>
    </boxset>
</xmeml>

会产生想要的正确结果:

<xmeml>
   <boxset>
      <stream>
         <track>
            <image>
               <start>0</start>
               <end>90</end>
               <file id="abcde">
                  <key>95</key>
                  <string>1023</string>
                  <time>
                     <reel>142</reel>
                  </time>
               </file>
            </image>
            <image>
               <start>90</start>
               <end>120</end>
               <file id="bcdef">
                  <key>55</key>
                  <string>1023</string>
                  <time>
                     <reel>64</reel>
                  </time>
               </file>
            </image>
         </track>
         <track>
            <image>
               <start>120</start>
               <end>130</end>
               <file id="abcde">
                  <key>95</key>
                  <string>1023</string>
                  <time>
                     <reel>142</reel>
                  </time>
               </file>
            </image>
            <image>
               <start>130</start>
               <end>180</end>
               <file id="cdefg">
                  <key>92</key>
                  <string>1023</string>
                  <time>
                     <reel>194</reel>
                  </time>
               </file>
            </image>
         </track>
      </stream>
   </boxset>
</xmeml>

答案 1 :(得分:0)

我认为只需处理file而不打扰image

就更简单了
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:key name="file" match="file[*]" use="@id"/>

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

  <xsl:template match="file[not(*)]">
    <xsl:copy-of select="key('file', @id)" />
  </xsl:template>

</xsl:stylesheet>