XML 根据匹配将除 text() 之外的所有内容从一个 XML 复制到另一个
XML to copy all but text() from one XML to another, based on match
您好 – 我是 XSLT 新手:
我有两个 XML TEI 文件,其中包含一些匹配元素。我想用第二个文件 lookup.xml
中相应的 <w>
元素替换第一个文件 TEI_test.xml
中的每个元素,这样第一个文件中的属性 @lemma
匹配第二个文件 (lookup.xml
) 中的属性 @lemma
。除了实际的 text()
之外,还应复制所有属性和子项。如果没有匹配项,则应保留原始 TEI_test.xml
元素。
这是 TEI_test.xml
文件:
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader><fileDesc>
<titleStmt>
<title></title>
</titleStmt>
<publicationStmt><publisher></publisher></publicationStmt>
<sourceDesc><p></p></sourceDesc>
</fileDesc>
</teiHeader><text><body>
<p xml:lang="arn" n="3">
<w xml:lang="" lemma="ta">ta</w>
<w xml:lang="" lemma="ella">ella</w>
<w xml:lang="" lemma="rüpü">rùpù</w>
<w xml:lang="" lemma="rüpüwe">rùpùwe</w>
</p>
</body>
</text>
</TEI>
这是查找 table:lookup.xml
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader><fileDesc>
<titleStmt>
<title></title>
</titleStmt>
<publicationStmt><publisher></publisher></publicationStmt>
<sourceDesc><p></p></sourceDesc>
</fileDesc>
</teiHeader><text><body><p>
<w xml:lang="arn" lemma="mew" pos="P"><m baseForm="mew" type="root" corresp="P">meu</m></w>
<w xml:lang="arn" lemma="ta" pos="DA"><m baseForm="ta" type="root" corresp="DA">ta</m></w>
<w xml:lang="arn" lemma="rüpü" pos="N" corresp="path/road"><m baseForm="rüpü" type="root" corresp="path/road">rüpü</m></w>
<w xml:lang="arn" lemma="rüpüwe" pos="N" corresp="place of path/road"><m baseForm="rüpü" type="root" corresp="path/road">rüpü</m><m baseForm="we" type="instrumental">we</m></w>
</p>
</body></text></TEI>
我想出的XSLT如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:tei="http://www.tei-c.org/ns/1.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:param name="path-to-lookup" select="'lookup1.xml'" />
<xsl:param name="path-to-orig" select="'TEI_test.xml.xml'" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tei:w">
<xsl:choose>
<xsl:when test="@lemma =document($path-to-lookup)//tei:w[@lemma]">
<xsl:copy-of select="document($path-to-lookup)//tei:w[@lemma=current()/@lemma]">
</xsl:copy-of>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise></xsl:choose>
<xsl:choose>
<xsl:when test="@lemma =document($path-to-lookup)//tei:w[@lemma]">
<xsl:copy-of select="document($path-to-orig)//tei:w[text()=current()/text()]"/>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise></xsl:choose>
</xsl:template>
</xsl:stylesheet>`
虽然这设法复制了所有存在 w[@lemma]
匹配的 <w>
节点,但在保存 w/text()
时并没有产生预期的结果,这将由第二个 <xsl:choose>
系列解决。这是我得到的:
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader>
<fileDesc>
<titleStmt>
<title/>
</titleStmt>
<publicationStmt>
<publisher/>
</publicationStmt>
<sourceDesc>
<p/>
</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<body>
<p xml:lang="arn" n="3">
<w xml:lang="arn" lemma="ta" pos="DA">
<m baseForm="ta" type="root" corresp="DA">ta</m>
</w>
<w xml:lang="" lemma="ta">ta</w>
<w xml:lang="" lemma="ella">ella</w>
<w xml:lang="arn" lemma="rüpü" pos="N" corresp="path/road">
<m baseForm="rüpü" type="root" corresp="path/road">rüpü</m>
</w>
<w xml:lang="" lemma="rüpü">rùpù</w>
<w xml:lang="arn" lemma="rüpüwe" pos="N" corresp="place of path/road">
<m baseForm="rüpü" type="root" corresp="path/road">rüpü</m>
<m baseForm="we" type="instrumental">we</m>
</w>
</p>
</body>
</text>
</TEI>
其实我想得到的是:
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader>
<fileDesc>
<titleStmt>
<title/>
</titleStmt>
<publicationStmt>
<publisher/>
</publicationStmt>
<sourceDesc>
<p/>
</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<body>
<p xml:lang="arn" n="3">
<w xml:lang="arn" lemma="ta" pos="DA">
<m baseForm="ta" type="root" corresp="DA">ta</m>
</w>
<w xml:lang="" lemma="ella">ella</w>
<w xml:lang="arn" lemma="rüpü" pos="N" corresp="path/road">
<m baseForm="rüpü" type="root" corresp="path/road">rùpù</m>
</w>
<w xml:lang="arn"
lemma="rüpüwe" pos="N" corresp="place of path/road">
<m baseForm="rüpü" type="root" corresp="path/road">rùpùwe</m>
<m baseForm="we" type="instrumental">rùpùwe</m>
</w>
</p>
</body>
</text>
</TEI>
有什么想法吗?
我会使用密钥,在 XSLT 2/3 中,您可以使用 key
函数的第三个参数、模式和隧道参数优雅地完成它:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath-default-namespace="http://www.tei-c.org/ns/1.0"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="lookup-doc" select="document('lookup.xml')"/>
<xsl:key name="ref" match="*[@lemma]" use="@lemma"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:mode name="ref-copy" on-no-match="shallow-copy"/>
<xsl:template match="*[key('ref', @lemma, $lookup-doc)]">
<xsl:apply-templates select="key('ref', @lemma, $lookup-doc)" mode="ref-copy">
<xsl:with-param name="text" select="string()" tunnel="yes"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="text()" mode="ref-copy">
<xsl:param name="text" tunnel="yes"/>
<xsl:value-of select="$text"/>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/3NSSEuR
对于 XSLT 1,您需要阐明两种模式的身份转换,并让第二种模式处理参数而不是依赖隧道参数。您还需要从模板内部检查查找是否存在,使用 for-each select="$lookup-doc"
更改上下文。哦,你必须为命名空间声明一个前缀:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:tei="http://www.tei-c.org/ns/1.0"
exclude-result-prefixes="exsl msxml"
version="1.0">
<xsl:param name="lookup-doc" select="document('lookup.xml')"/>
<xsl:key name="ref" match="tei:*[@lemma]" use="@lemma"/>
<xsl:template match="@* | node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@* | node()" mode="ref-copy">
<xsl:param name="text"/>
<xsl:copy>
<xsl:apply-templates select="@* | node()" mode="ref-copy">
<xsl:with-param name="text" select="$text"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="tei:*[@lemma]">
<xsl:variable name="this" select="."/>
<xsl:for-each select="$lookup-doc">
<xsl:variable name="ref-el" select="key('ref', $this/@lemma)"/>
<xsl:choose>
<xsl:when test="$ref-el">
<xsl:apply-templates select="$ref-el" mode="ref-copy">
<xsl:with-param name="text" select="string($this)"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="$this">
<xsl:call-template name="identity"/>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template match="text()" mode="ref-copy">
<xsl:param name="text"/>
<xsl:value-of select="$text"/>
</xsl:template>
</xsl:stylesheet>
您好 – 我是 XSLT 新手:
我有两个 XML TEI 文件,其中包含一些匹配元素。我想用第二个文件 lookup.xml
中相应的 <w>
元素替换第一个文件 TEI_test.xml
中的每个元素,这样第一个文件中的属性 @lemma
匹配第二个文件 (lookup.xml
) 中的属性 @lemma
。除了实际的 text()
之外,还应复制所有属性和子项。如果没有匹配项,则应保留原始 TEI_test.xml
元素。
这是 TEI_test.xml
文件:
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader><fileDesc>
<titleStmt>
<title></title>
</titleStmt>
<publicationStmt><publisher></publisher></publicationStmt>
<sourceDesc><p></p></sourceDesc>
</fileDesc>
</teiHeader><text><body>
<p xml:lang="arn" n="3">
<w xml:lang="" lemma="ta">ta</w>
<w xml:lang="" lemma="ella">ella</w>
<w xml:lang="" lemma="rüpü">rùpù</w>
<w xml:lang="" lemma="rüpüwe">rùpùwe</w>
</p>
</body>
</text>
</TEI>
这是查找 table:lookup.xml
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader><fileDesc>
<titleStmt>
<title></title>
</titleStmt>
<publicationStmt><publisher></publisher></publicationStmt>
<sourceDesc><p></p></sourceDesc>
</fileDesc>
</teiHeader><text><body><p>
<w xml:lang="arn" lemma="mew" pos="P"><m baseForm="mew" type="root" corresp="P">meu</m></w>
<w xml:lang="arn" lemma="ta" pos="DA"><m baseForm="ta" type="root" corresp="DA">ta</m></w>
<w xml:lang="arn" lemma="rüpü" pos="N" corresp="path/road"><m baseForm="rüpü" type="root" corresp="path/road">rüpü</m></w>
<w xml:lang="arn" lemma="rüpüwe" pos="N" corresp="place of path/road"><m baseForm="rüpü" type="root" corresp="path/road">rüpü</m><m baseForm="we" type="instrumental">we</m></w>
</p>
</body></text></TEI>
我想出的XSLT如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:tei="http://www.tei-c.org/ns/1.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:param name="path-to-lookup" select="'lookup1.xml'" />
<xsl:param name="path-to-orig" select="'TEI_test.xml.xml'" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tei:w">
<xsl:choose>
<xsl:when test="@lemma =document($path-to-lookup)//tei:w[@lemma]">
<xsl:copy-of select="document($path-to-lookup)//tei:w[@lemma=current()/@lemma]">
</xsl:copy-of>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise></xsl:choose>
<xsl:choose>
<xsl:when test="@lemma =document($path-to-lookup)//tei:w[@lemma]">
<xsl:copy-of select="document($path-to-orig)//tei:w[text()=current()/text()]"/>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise></xsl:choose>
</xsl:template>
</xsl:stylesheet>`
虽然这设法复制了所有存在 w[@lemma]
匹配的 <w>
节点,但在保存 w/text()
时并没有产生预期的结果,这将由第二个 <xsl:choose>
系列解决。这是我得到的:
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader>
<fileDesc>
<titleStmt>
<title/>
</titleStmt>
<publicationStmt>
<publisher/>
</publicationStmt>
<sourceDesc>
<p/>
</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<body>
<p xml:lang="arn" n="3">
<w xml:lang="arn" lemma="ta" pos="DA">
<m baseForm="ta" type="root" corresp="DA">ta</m>
</w>
<w xml:lang="" lemma="ta">ta</w>
<w xml:lang="" lemma="ella">ella</w>
<w xml:lang="arn" lemma="rüpü" pos="N" corresp="path/road">
<m baseForm="rüpü" type="root" corresp="path/road">rüpü</m>
</w>
<w xml:lang="" lemma="rüpü">rùpù</w>
<w xml:lang="arn" lemma="rüpüwe" pos="N" corresp="place of path/road">
<m baseForm="rüpü" type="root" corresp="path/road">rüpü</m>
<m baseForm="we" type="instrumental">we</m>
</w>
</p>
</body>
</text>
</TEI>
其实我想得到的是:
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader>
<fileDesc>
<titleStmt>
<title/>
</titleStmt>
<publicationStmt>
<publisher/>
</publicationStmt>
<sourceDesc>
<p/>
</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<body>
<p xml:lang="arn" n="3">
<w xml:lang="arn" lemma="ta" pos="DA">
<m baseForm="ta" type="root" corresp="DA">ta</m>
</w>
<w xml:lang="" lemma="ella">ella</w>
<w xml:lang="arn" lemma="rüpü" pos="N" corresp="path/road">
<m baseForm="rüpü" type="root" corresp="path/road">rùpù</m>
</w>
<w xml:lang="arn"
lemma="rüpüwe" pos="N" corresp="place of path/road">
<m baseForm="rüpü" type="root" corresp="path/road">rùpùwe</m>
<m baseForm="we" type="instrumental">rùpùwe</m>
</w>
</p>
</body>
</text>
</TEI>
有什么想法吗?
我会使用密钥,在 XSLT 2/3 中,您可以使用 key
函数的第三个参数、模式和隧道参数优雅地完成它:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath-default-namespace="http://www.tei-c.org/ns/1.0"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="lookup-doc" select="document('lookup.xml')"/>
<xsl:key name="ref" match="*[@lemma]" use="@lemma"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:mode name="ref-copy" on-no-match="shallow-copy"/>
<xsl:template match="*[key('ref', @lemma, $lookup-doc)]">
<xsl:apply-templates select="key('ref', @lemma, $lookup-doc)" mode="ref-copy">
<xsl:with-param name="text" select="string()" tunnel="yes"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="text()" mode="ref-copy">
<xsl:param name="text" tunnel="yes"/>
<xsl:value-of select="$text"/>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/3NSSEuR
对于 XSLT 1,您需要阐明两种模式的身份转换,并让第二种模式处理参数而不是依赖隧道参数。您还需要从模板内部检查查找是否存在,使用 for-each select="$lookup-doc"
更改上下文。哦,你必须为命名空间声明一个前缀:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:tei="http://www.tei-c.org/ns/1.0"
exclude-result-prefixes="exsl msxml"
version="1.0">
<xsl:param name="lookup-doc" select="document('lookup.xml')"/>
<xsl:key name="ref" match="tei:*[@lemma]" use="@lemma"/>
<xsl:template match="@* | node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@* | node()" mode="ref-copy">
<xsl:param name="text"/>
<xsl:copy>
<xsl:apply-templates select="@* | node()" mode="ref-copy">
<xsl:with-param name="text" select="$text"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="tei:*[@lemma]">
<xsl:variable name="this" select="."/>
<xsl:for-each select="$lookup-doc">
<xsl:variable name="ref-el" select="key('ref', $this/@lemma)"/>
<xsl:choose>
<xsl:when test="$ref-el">
<xsl:apply-templates select="$ref-el" mode="ref-copy">
<xsl:with-param name="text" select="string($this)"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="$this">
<xsl:call-template name="identity"/>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template match="text()" mode="ref-copy">
<xsl:param name="text"/>
<xsl:value-of select="$text"/>
</xsl:template>
</xsl:stylesheet>