问题
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 file
s 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 key
s 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