2

我有一个简单的 xml 文本和一个小人物。我想找到文中提到的所有“人”,并使用人物画像中的信息对其进行标记。我的文字如下所示:

<text>
    <div>
        <p>Mohandas Ghandi was an Indian lawyer, born in 1869.</p>
        <p>Albert Einstein was a German physicist, born in 1879.</p>
        <p>Helen Keller was an American author, born in 1880.</p>
        <p>Joan Baez is an American singer/songwriter, born in 1941.</p>
    </div>
</text>

我的人像是这样的:

<people>
    <person id="ghandi">
        <name>Mohandas Ghandi</name>
        <birthPlace>Porbandar, India</birthPlace>
    </person>
    <person id="einstein">
        <name>Albert Einstein</name>
        <birthPlace>Ulm, Germany</birthPlace>
    </person>
    <person id="keller">
        <name>Helen Keller</name>
        <birthPlace>Tuscumbia, USA</birthPlace>
    </person>
</people>

到目前为止,我有这个 xslt (2.0):

<xsl:variable name="personography" select="doc('people.xml')"/>   
<xsl:variable name="pName" select="$personography//person[1]/name"/>
<xsl:variable name="pId" select="$personography//person[1]/@id"/>

<xsl:template match="*">
    <xsl:copy>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>    

<xsl:template name="encNames" match="text()">
    <xsl:analyze-string select="."  regex="{$pName}">
        <xsl:matching-substring>
            <persName corresp="{concat('people.xml#',$pId)}">
                <xsl:value-of select="."/>
            </persName>
        </xsl:matching-substring>
        <xsl:non-matching-substring>
            <xsl:copy-of select="."/>
        </xsl:non-matching-substring>
    </xsl:analyze-string>
</xsl:template>

我得到了这个:

<text>
    <div>
        <p><persName corresp="people.xml#ghandi">Mohandas Ghandi</persName> was an Indian lawyer, born in 1869.</p>
        <p>Albert Einstein was a German physicist, born in 1879.</p>
        <p>Helen Keller was an American author, born in 1880.</p>
        <p>Joan Baez is an American singer/songwriter, born in 1941.</p>
    </div>
</text>

所以,我的问题是,我如何标记文本中的其他人?我认为它需要一个使用跟随兄弟的函数,但我没有比这更进一步。我错过了什么?我至少在正确的轨道上吗?谢谢。

4

2 回答 2

1

我要做的是更改pName以返回一系列名称而不是第一个人的姓名。然后我会使用该序列来构造一个新的正则表达式。

例子...

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:preserve-space elements="p"/>

    <xsl:variable name="personography" select="doc('people.xml')"/>
    <xsl:variable name="pName" select="$personography/*/person/name"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template> 

    <xsl:template match="text()" priority="1">
        <xsl:analyze-string select="."  regex="({string-join($pName,'|')})">
            <xsl:matching-substring>
                <persName corresp="{concat('people.xml#',$personography/*/person[name=current()]/@id)}">
                    <xsl:value-of select="."/>
                </persName>
            </xsl:matching-substring>
            <xsl:non-matching-substring>
                <xsl:copy-of select="."/>
            </xsl:non-matching-substring>
        </xsl:analyze-string>
    </xsl:template>

</xsl:stylesheet>
于 2013-10-09T01:26:15.660 回答
0

它有点冗长,可能会被优化或重构,但可以。

该模板将遍历每个人并应用分析字符串。结果在一个变量中,每个人都$person-matches用a 调用。<match>

如果存在包含 a 的匹配项<persName>,则使用该匹配项。否则,使用模板中匹配的原始文本。

<xsl:template match="text()">
    <xsl:variable name="txt" select="."/>

    <xsl:variable name="person-matches">
      <xsl:for-each select="$personography/person">
        <xsl:variable name="person" select="."/>
          <match>
            <xsl:analyze-string select="$txt"  regex="({$person/name})">
                <xsl:matching-substring>
                    <persName corresp="{concat('people.xml#',$person/@id)}">
                        <xsl:value-of select="regex-group(1)"/>
                    </persName>
                </xsl:matching-substring>
                <xsl:non-matching-substring>
                    <xsl:value-of select="."/>
                </xsl:non-matching-substring>
            </xsl:analyze-string>
          </match>
        </xsl:for-each>
    </xsl:variable>

    <xsl:choose>
        <xsl:when test="$person-matches/match[persName]">
            <xsl:sequence select="$person-matches/match[persName]/node()"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy-of select="."/>
        </xsl:otherwise>
    </xsl:choose>

</xsl:template>
于 2013-10-09T01:19:12.700 回答