匹配来自两个 XML 文件的 ID,并从具有相同 ID 的元素中获取字符串
Match IDs from two XML files and get strings from element with same ID
如何确保只有第二个文件中匹配的人物元素的persName成为第一个文件中人物元素的persName?
所以我有两个 XML 个文件。
第一个看起来像这样:
...
<teiHeader>
...
<profileDesc>
...
<particDesc>
<listPerson>
<person role="" ref="#11988">
<persName/>
</person>
<person role="" ref="#13163">
<persName/>
</person>
<person role="" ref="#38909">
<persName/>
</person>
<person role="" ref="#38969">
<persName/>
</person>
<person role="" ref="#11910">
<persName/>
</person>
</listPerson>
</particDesc>
</profileDesc>
...
</teiHeader>
...
它包含 @ref
属性中人员的 ID。
第二个 (= listPerson.xml) 看起来像这样:
...
</teiHeader>
<text>
<body>
<div type="persons">
<person xml:id="#11988">
<persName>
<forename>Forename1</forename>
<surname>Surname1</surname>
<persName>
</person>
<person xml:id="#13163">
<persName>
<forename>Forename2</forename>
<surname>Surname2</surname>
<persName>
</person>
<person xml:id="#38909">
<persName>
<forename>Forename3</forename>
<surname>Surname3</surname>
<persName>
</person>
<person xml:id="#38969">
<persName>
<forename>Forename4</forename>
<surname>Surname4</surname>
<persName>
</person>
<person xml:id="#11910">
<persName>
<forename>Forename5</forename>
<surname>Surname5</surname>
<persName>
</person>
</div>
</body>
</text>
因此此文件包含与第一个文件相同的 ID,但在 @xml:id
属性中。此外,它还包含 <persName>
.
中的人员姓名
我要做的是匹配ID(@ref
和@xml:id
的属性值)然后复制<forename>
和<surname>
到使用 XSLT 在第一个文件中的正确位置。
我当前的样式表如下所示:
<?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:output method="xml" version="1.0" indent="yes"/>
<!-- copy all -->
<xsl:template match="@* | node()" name="identity-copy">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- match ids, get persName -->
<xsl:variable name="listPers" select="document('listPerson.xml')"/>
<xsl:template match="//tei:persName">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<xsl:variable name="pers-ref" select="//tei:person/@ref"/>
<xsl:variable name="pers-info" select="$listPers//tei:person[@xml:id=$pers-ref]/." />
<xsl:for-each select="$pers-info">
<xsl:value-of select="tei:persName/tei:forename,tei:persName/tei:surname"/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
目前,这不起作用。我得到的是这个(如文件 1 中所希望的那样):
<person role="" ref="#11988">
<persName>Forename5 Surname5Forename4 Surname4Forename3 Surname3Forename2 Surname2Forename1 Surname1</persName>
</person>
<person role="" ref="#13163">
<persName>Forename5 Surname5Forename4 Surname4Forename3 Surname3Forename2 Surname2Forename1 Surname1</persName>
</person>
等等...
我想得到的是:
<person role="" ref="#11988">
<persName>Forename1 Surname1</persName>
</person>
<person role="" ref="#13163">
<persName>Forename2 Surname2</persName>
</person>
等
(但是不要假设persNames是有序的,这都是关于属性匹配的。)
提前致谢!
<xsl:variable name="pers-ref" select="//tei:person/@ref"/>
将 select 所有 的 @ref
tei:person
s - 这就是使用以 //
开头的绝对路径的原因做。你只想要当前的人。
要么使用相对路径 - 在 <xsl:template>
中,您位于 persName
元素中,您感兴趣的 @ref
属性在父元素中:
<xsl:variable name="pers-ref" select="../@ref"/>
或者您完全跳过额外变量并使用 current()
XSLT 函数:
<xsl:template match="tei:persName">
<xsl:variable name="pers-info" select="$listPers//tei:person[@xml:id=current()/../@ref]/tei:persName" />
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:value-of select="$pers-info/tei:forename, $pers-info/tei:surname" />
</xsl:copy>
</xsl:template>
另请注意,match
表达式不需要锚定。 match="//tei:persName"
没用。 match="tei:persName"
更好。
我建议使用 key 来解析交叉引用。这是一个 简化的 示例:
XML
<teiHeader>
<profileDesc>
<particDesc>
<listPerson>
<person role="" ref="#11988">
<persName/>
</person>
<person role="" ref="#13163">
<persName/>
</person>
<person role="" ref="#38909">
<persName/>
</person>
<person role="" ref="#38969">
<persName/>
</person>
<person role="" ref="#11910">
<persName/>
</person>
</listPerson>
</particDesc>
</profileDesc>
</teiHeader>
listPerson.xml(固定为合式!!)
<text>
<body>
<div type="persons">
<person xml:id="#11988">
<persName>
<forename>Forename1</forename>
<surname>Surname1</surname>
</persName>
</person>
<person xml:id="#13163">
<persName>
<forename>Forename2</forename>
<surname>Surname2</surname>
</persName>
</person>
<person xml:id="#38909">
<persName>
<forename>Forename3</forename>
<surname>Surname3</surname>
</persName>
</person>
<person xml:id="#38969">
<persName>
<forename>Forename4</forename>
<surname>Surname4</surname>
</persName>
</person>
<person xml:id="#11910">
<persName>
<forename>Forename5</forename>
<surname>Surname5</surname>
</persName>
</person>
</div>
</body>
</text>
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:param name="listPers" select="document('listPerson.xml')"/>
<xsl:key name="pers" match="person" use="@xml:id" />
<xsl:template match="teiHeader">
<output>
<xsl:for-each select="//person">
<xsl:copy>
<xsl:copy-of select="@*"/>
<persName>
<xsl:value-of select="key('pers', @ref, $listPers)/persName/(forename, surname)" />
</persName>
</xsl:copy>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
结果
<?xml version="1.0" encoding="utf-8"?>
<output>
<person role="" ref="#11988">
<persName>Forename1 Surname1</persName>
</person>
<person role="" ref="#13163">
<persName>Forename2 Surname2</persName>
</person>
<person role="" ref="#38909">
<persName>Forename3 Surname3</persName>
</person>
<person role="" ref="#38969">
<persName>Forename4 Surname4</persName>
</person>
<person role="" ref="#11910">
<persName>Forename5 Surname5</persName>
</person>
</output>
如何确保只有第二个文件中匹配的人物元素的persName成为第一个文件中人物元素的persName?
所以我有两个 XML 个文件。
第一个看起来像这样:
...
<teiHeader>
...
<profileDesc>
...
<particDesc>
<listPerson>
<person role="" ref="#11988">
<persName/>
</person>
<person role="" ref="#13163">
<persName/>
</person>
<person role="" ref="#38909">
<persName/>
</person>
<person role="" ref="#38969">
<persName/>
</person>
<person role="" ref="#11910">
<persName/>
</person>
</listPerson>
</particDesc>
</profileDesc>
...
</teiHeader>
...
它包含 @ref
属性中人员的 ID。
第二个 (= listPerson.xml) 看起来像这样:
...
</teiHeader>
<text>
<body>
<div type="persons">
<person xml:id="#11988">
<persName>
<forename>Forename1</forename>
<surname>Surname1</surname>
<persName>
</person>
<person xml:id="#13163">
<persName>
<forename>Forename2</forename>
<surname>Surname2</surname>
<persName>
</person>
<person xml:id="#38909">
<persName>
<forename>Forename3</forename>
<surname>Surname3</surname>
<persName>
</person>
<person xml:id="#38969">
<persName>
<forename>Forename4</forename>
<surname>Surname4</surname>
<persName>
</person>
<person xml:id="#11910">
<persName>
<forename>Forename5</forename>
<surname>Surname5</surname>
<persName>
</person>
</div>
</body>
</text>
因此此文件包含与第一个文件相同的 ID,但在 @xml:id
属性中。此外,它还包含 <persName>
.
我要做的是匹配ID(@ref
和@xml:id
的属性值)然后复制<forename>
和<surname>
到使用 XSLT 在第一个文件中的正确位置。
我当前的样式表如下所示:
<?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:output method="xml" version="1.0" indent="yes"/>
<!-- copy all -->
<xsl:template match="@* | node()" name="identity-copy">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- match ids, get persName -->
<xsl:variable name="listPers" select="document('listPerson.xml')"/>
<xsl:template match="//tei:persName">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<xsl:variable name="pers-ref" select="//tei:person/@ref"/>
<xsl:variable name="pers-info" select="$listPers//tei:person[@xml:id=$pers-ref]/." />
<xsl:for-each select="$pers-info">
<xsl:value-of select="tei:persName/tei:forename,tei:persName/tei:surname"/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
目前,这不起作用。我得到的是这个(如文件 1 中所希望的那样):
<person role="" ref="#11988">
<persName>Forename5 Surname5Forename4 Surname4Forename3 Surname3Forename2 Surname2Forename1 Surname1</persName>
</person>
<person role="" ref="#13163">
<persName>Forename5 Surname5Forename4 Surname4Forename3 Surname3Forename2 Surname2Forename1 Surname1</persName>
</person>
等等...
我想得到的是:
<person role="" ref="#11988">
<persName>Forename1 Surname1</persName>
</person>
<person role="" ref="#13163">
<persName>Forename2 Surname2</persName>
</person>
等 (但是不要假设persNames是有序的,这都是关于属性匹配的。)
提前致谢!
<xsl:variable name="pers-ref" select="//tei:person/@ref"/>
将 select 所有 的 @ref
tei:person
s - 这就是使用以 //
开头的绝对路径的原因做。你只想要当前的人。
要么使用相对路径 - 在 <xsl:template>
中,您位于 persName
元素中,您感兴趣的 @ref
属性在父元素中:
<xsl:variable name="pers-ref" select="../@ref"/>
或者您完全跳过额外变量并使用 current()
XSLT 函数:
<xsl:template match="tei:persName">
<xsl:variable name="pers-info" select="$listPers//tei:person[@xml:id=current()/../@ref]/tei:persName" />
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:value-of select="$pers-info/tei:forename, $pers-info/tei:surname" />
</xsl:copy>
</xsl:template>
另请注意,match
表达式不需要锚定。 match="//tei:persName"
没用。 match="tei:persName"
更好。
我建议使用 key 来解析交叉引用。这是一个 简化的 示例:
XML
<teiHeader>
<profileDesc>
<particDesc>
<listPerson>
<person role="" ref="#11988">
<persName/>
</person>
<person role="" ref="#13163">
<persName/>
</person>
<person role="" ref="#38909">
<persName/>
</person>
<person role="" ref="#38969">
<persName/>
</person>
<person role="" ref="#11910">
<persName/>
</person>
</listPerson>
</particDesc>
</profileDesc>
</teiHeader>
listPerson.xml(固定为合式!!)
<text>
<body>
<div type="persons">
<person xml:id="#11988">
<persName>
<forename>Forename1</forename>
<surname>Surname1</surname>
</persName>
</person>
<person xml:id="#13163">
<persName>
<forename>Forename2</forename>
<surname>Surname2</surname>
</persName>
</person>
<person xml:id="#38909">
<persName>
<forename>Forename3</forename>
<surname>Surname3</surname>
</persName>
</person>
<person xml:id="#38969">
<persName>
<forename>Forename4</forename>
<surname>Surname4</surname>
</persName>
</person>
<person xml:id="#11910">
<persName>
<forename>Forename5</forename>
<surname>Surname5</surname>
</persName>
</person>
</div>
</body>
</text>
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:param name="listPers" select="document('listPerson.xml')"/>
<xsl:key name="pers" match="person" use="@xml:id" />
<xsl:template match="teiHeader">
<output>
<xsl:for-each select="//person">
<xsl:copy>
<xsl:copy-of select="@*"/>
<persName>
<xsl:value-of select="key('pers', @ref, $listPers)/persName/(forename, surname)" />
</persName>
</xsl:copy>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
结果
<?xml version="1.0" encoding="utf-8"?>
<output>
<person role="" ref="#11988">
<persName>Forename1 Surname1</persName>
</person>
<person role="" ref="#13163">
<persName>Forename2 Surname2</persName>
</person>
<person role="" ref="#38909">
<persName>Forename3 Surname3</persName>
</person>
<person role="" ref="#38969">
<persName>Forename4 Surname4</persName>
</person>
<person role="" ref="#11910">
<persName>Forename5 Surname5</persName>
</person>
</output>