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

无人久伴 提交于 2019-12-13 06:08:50

问题


I have an XML that looks the Below.

I am trying to fill a filemaker record with all the values from each of the Image node attributes.

However notice that within the XML presented, if a Image node is used more than once, defined by its file id , its subsequent children's elements are not present.

I have the current sample xsl below that is basically working but I would like to add a conditional evaluation to the stylesheet that says: In English: if the 'key' element does not exist the find the first preceding matching and use the values from those elements. The same would apply for the 'string and 'reel' elements.

The result will fill each records columns with all the relevant data instead of what is now sometimes only partial data for such duplicated files.

Apologies for my poor description.

Any help will be greatly appreciated.

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:template match='/'>
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
<ERRORCODE>0</ERRORCODE>
<PRODUCT BUILD="11/13/2002" NAME="Filemaker Pro" VERSION="6.0V4"/>
<DATABASE DATEFORMAT="d/M/yyyy" LAYOUT="" NAME="combotest.fp7" RECORDS="" TIMEFORMAT="h:mm:ss a"/>
<METADATA>

<FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="start" TYPE="NUMBER"/>
<FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="end" TYPE="NUMBER"/>
<FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="fileID" TYPE="TEXT"/>

<FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="key" TYPE="NUMBER"/>
<FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="string" TYPE="NUMBER"/>
<FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="reel" TYPE="NUMBER"/>
</METADATA>
<xsl:for-each select=" //image ">


<RESULTSET FOUND="">

<ROW MODID="" RECORDID="">

<COL><DATA><xsl:value-of select="./start" /></DATA></COL>
<COL><DATA><xsl:value-of select="./end" /></DATA></COL>
<COL><DATA><xsl:value-of select="./file/@id" /></DATA></COL>

<COL><DATA><xsl:value-of select="./file/key" /></DATA></COL>
<COL><DATA><xsl:value-of select="./file/string" /></DATA></COL>
<COL><DATA><xsl:value-of select="./file/time/reel" /></DATA></COL>

</ROW>

</xsl:for-each>


</RESULTSET></FMPXMLRESULT>
</xsl:template>
</xsl:stylesheet>

If the XML were to be filled they way Id like to see it it would look like this.

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

回答1:


You need to define a XSLT key to find file definition by its ID:

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

Here the [*] predicate ensures that only files with at least one child element will be indexed by their id. Since each file has only one such a definition, this is exactly what we need. Then you find the definition using the key() function:

...
<COL><DATA><xsl:value-of select="./end" /></DATA></COL>
<xsl:variable name="file" select="key('file', file/@id)" />
<COL><DATA><xsl:value-of select="$file/@id" /></DATA></COL>
<COL><DATA><xsl:value-of select="$file/key" /></DATA></COL>
<COL><DATA><xsl:value-of select="$file/string" /></DATA></COL>
<COL><DATA><xsl:value-of select="$file/time/reel" /></DATA></COL>
...

XSLT keys are added at the top level of the stylesheet (i.e. among xsl:template, xsl:output, etc.).



来源:https://stackoverflow.com/questions/11879521/xslt-find-element-values-from-first-preceding-item-with-matching-name-id-usi

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