XSLT lookup from external xml file

倖福魔咒の 提交于 2020-07-08 02:47:49

问题


I am aware that there are plenty of questions (and answers) here on the lookup from external xml files via xslt. However, I still haven't got my head around the logic of the key function so I'm having a hard time applying other solutions to my use case.

I have two xml files:

versA.xml

<TEI>
  <div>
    <l id="A001" corresp="B001">First line of VersA</l>
    <l id="A002" corresp="B002">Second line of VersA</l>
    <l id="A003" corresp="B003">Third line of VersA</l>
  </div>
</TEI>

and

versB.xml

<TEI>
  <div>
    <l id="B001" corresp="A001">First line of VersB</l>
    <l id="B002" corresp="A002">Second line of VersB</l>
    <l id="B003" corresp="A003">Third line of VersB</l>
  </div>
</TEI>

The files refer to each other via the corresp-attribute.

I'm trying to figure out a xsl stylesheet (trans.xsl) that parses versA.xml, prints its own text node and then looks up the corresponding text node in versB.xml

trans.xsl

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

<xsl:variable name="vB" select="document('versB.xml')/TEI/div/l"/>

<xsl:template match="/TEI/div/l">
I found ID <xsl:value-of select="@id"/> in versA.xml.
How can I get the corresponding node in versB.xml which has the ID <xsl:value-of select="@corresp"/>?
</xsl:template>


</xsl:stylesheet>

What I can do is output the ids of versA.xml and access versB.xml. I find it extremely difficult however, to set up an appropriate key function that takes the corresp value from versA.xml to look up the corresponding id in versB.xml

I'd be happy if somebody could explain how this can be achieved.

For compatibility reasons xslt version 1.0 would be preferred.

I have updated my stylesheet according to the suggestions given in the comments. The following gives the desired output:

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

<xsl:key name="ref" match="TEI/div/l" use="@id"/>

<xsl:template match="/TEI/div/l">

  <xsl:variable name="corresp" select="@corresp"/>
  <xsl:value-of select="."/> corresponds to 
  <xsl:for-each select="document('versB.xml')">
     <xsl:value-of select="key('ref', $corresp)"/>
   </xsl:for-each>

</xsl:template>

</xsl:stylesheet>

回答1:


You need to declare a key with xsl:key, giving it a name you can choose, using a match pattern of the nodes you want to "index", you want to declare the key for, and defining a key value with the use attribute, an XPath expression:

<xsl:key name="ref" match="TEI/div/l" use="@id"/>

To use a key you call the key function with the name of the declared key as the first argument, the key value as the second argument and, in XSLT 2 or later, the document or subtree you want to search, as the third argument: key('ref', @corresp, document('versB.xml')).

If you are really restricted to XSLT 1 then, with two different documents, as the third argument of the key function is not supported, you need to switch the "context document" with for-each, for instance:

<!-- need to store value of main input document we want to lookup in variable -->
<xsl:variable name="corresp" select="@corresp"/>

<!-- now we change the context document to be able to apply the key function on secondary input -->
<xsl:for-each select="document('versB.xml')">
   <xsl:value-of select="key('ref', $corresp)"/>
</xsl:for-each>

Both example uses of the key function above assume you make them in the context of an xsl:template match="/TEI/div/l" so that @corresp selects the value of that attribute of an l element in your main input.



来源:https://stackoverflow.com/questions/60578625/xslt-lookup-from-external-xml-file

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