Reputation: 219
I have XML files where I need to replace the value of an element (idno[@type='code']) with a value from an external document.
I have to match the value based off of an eISBN in that external document.
XML file:
<book>
<idno type="online">3456789012345</idno>
<idno type="subject">Environment</idno>
<idno type="subject">Water</idno>
<idno type="subject">Policy</idno>
<idno type="code">135/B</idno>
<idno type="ID">43396</idno>
</book>
External document (a2r-test.xml):
<root>
<row>
<eISBN>1234567890123</eISBN>
<uri>book1</uri>
<a2r>89364</a2r>
</row>
<row>
<eISBN>3456789012345</eISBN>
<uri>book2</uri>
<a2r>E135</a2r>
</row>
<row>
<eISBN>5678901234567</eISBN>
<uri>book3</uri>
<a2r>B10765/B</a2r>
</row>
</root>
XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tei="http://www.tei-c.org/ns/1.0"
exclude-result-prefixes="xs"
version="2.0">
<xsl:variable name="a2r" select="document('a2r-test.xml')"/>
<xsl:template match="tei:idno[@type='code']">
<xsl:if test="$a2r//row/eISBN = preceding-sibling::tei:idno[@type='online']">
<xsl:element name="idno">
<xsl:attribute name="type" select="'code'"/>
**<xsl:value-of select="?"/>**
</xsl:element>
</xsl:if>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
What do I place in the xsl:value-of select to pull in the value of "a2r" (following-sibling::eISBN - that matches the idno[@type='online'])
Final expected result:
<book>
<idno type="online">3456789012345</idno>
<idno type="subject">Environment</idno>
<idno type="subject">Water</idno>
<idno type="subject">Policy</idno>
<idno type="code">E135</idno>
<idno type="ID">43396</idno>
</book>
Thanks in advance.
Upvotes: 0
Views: 1716
Reputation: 116992
In general, it's best to use a key to resolve cross-references. Here's an example matching your given inputs:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="a2r-doc" select="document('a2r-test.xml')"/>
<xsl:key name="a2r-key" match="row" use="eISBN" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="idno[@type='code']">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:value-of select="key('a2r-key', ../idno[@type='online'], $a2r-doc)/a2r"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note:
You didn't show us your real input, which - judging from your XSLT - is in a namespace. In such case, you cannot use xsl:copy
(through the identity transform template) for some elements and xsl:element
(without a namespace) for others, or you will end up with the result being a mix of elements in different namespaces.
Upvotes: 3