XSLT 2.0:从不同文件中提取内容

时间:2013-10-17 09:02:59

标签: list xslt-2.0

我正在寻找这个解决方案很长一段时间,我想在放弃之前我试着在这里提出这个问题。

我有27个XML文件(在TEI中),我有一个XSLT样式表2.0。 我写了一个函数,它进入每个XML文件并创建一个新的html文件(所有指定人员的列表)。

我的XML中的指定人员看起来像这样:

<persName role="addressee">Herr <roleName>Prof. Dr.</roleName>XYY</persName>

或者那样:

<persName key="linktodatabank">Herr <roleName>Dr.</roleName> Hugo <surname>Müller</surname></persName>

<persName>Herr Heinz</persName>
<persName>Volkm</persName>

虽然(我的XSLT)不是一个好的解决方案,因为我将每个文件命名为:

<xsl:variable name="persName1" select="document('01_ML.xml')/tei:TEI//tei:persName"/>

var名称继续使用persName2,persName3等。文档名称依赖于相同的02_ML,03_ML等。我知道有一个计数器但不知道如何做到这一点会很好。 在我命名所有文档之后(我对提取placeNames和术语做同样的事情),我创建了一个集合(也不是一个好的解决方案)并尝试这样:

 <xsl:variable name="collection2" select="$persName1, $persName2, $persName3, $persName4, $persName5, $persName7, $persName8, $persName9,
                           $persName10, $persName11, $persName12, $persName13, $persName14, $persName15, $persName16, $persName17, $persName18, $persName19, $persName20"></xsl:variable> 
                       <html xmlns="http://www.w3.org/1999/xhtml">
                           <head>
                               <link rel="stylesheet" type="text/css" href="persName.css"/>
                               <title>Personenregister</title></head>
                           <body>
                             <h1 class="title">Personenregister</h1>
                              <ul> 

                                  <xsl:for-each select="$collection2">
                                   <xsl:sort select="string()" order="ascending"/>
                                   <li class="liste"> 
                                       <xsl:variable name="personen" select="normalize-space(string-join(.//text()[not(parent::tei:roleName)], ''))
                                           "></xsl:variable>
                                       <xsl:variable name="personen2" select="normalize-space(string-join(.//text()[not(parent::tei:surname)], ''))
                                           "></xsl:variable>

                                       <xsl:choose>
                                           <xsl:when test="@key">
                                               <xsl:choose>
                                                   <xsl:when test="exists(tei:roleName)"> <a href="{@key}" target="_blank">    <xsl:value-of select="concat($personen, ', ', tei:roleName)"/> </a>
                                                   </xsl:when>
                                                   <xsl:when test="exists(tei:surname)"><a href="{@key}" target="_blank">    <xsl:value-of select="concat($personen2, ', ', tei:surname, ', ', tei:roleName)"/> </a></xsl:when>

                                                   <xsl:otherwise><a href="{@key}" target="_blank"><xsl:value-of select="$personen"/></a></xsl:otherwise>
                                               </xsl:choose>

                                           </xsl:when>
                                           <xsl:otherwise>
                                               <xsl:choose>
                                                   <xsl:when test="exists(tei:roleName)"><xsl:value-of select="concat($personen, ', ', tei:roleName)"/>

                                                   </xsl:when>
                                                   <xsl:otherwise><xsl:value-of select="$personen"/>
                                                      </xsl:otherwise>
                                               </xsl:choose>
                                           </xsl:otherwise>
                                       </xsl:choose>


                                   </li>  

我的html列表应按字母顺序命名所有人,首先是姓氏,然后是姓名,然后是姓名。 但我不知道如何删除有时出现在我的persName中的“Herr”或“Herrn”。 你知道怎么做的吗?

另一件事是,我想删除所有双重名称。有些名字出现的次数超过一次。

我的新HTML列表应如下所示:

     <li class="liste"><a href="http://d-nb.info/gnd/118738380" target="_blank">Neisser, Albert </a></li>
<li class="liste">Spiethoff, Prof.</li>

我觉得我对这些代码搞得很糟糕。如果有人可以帮助我,那就太好了。

谢谢!

更新

谢谢你的帮助!看起来好多了!!我忘了提到我把这个代码放在我的身体里,因为我使用的是xsl:result-document。因此我不能使用xsl:template。我尝试了不同的版本并找到了这个解决方案:

    <xsl:result-document href="persName.html" method="html" encoding="UTF-16"> 
 <xsl:variable name="collection2"  select="collection('./?select=*_ML.xml')//tei:persName[not(.=preceding-sibling::node())]"> </xsl:variable>
 <xsl:variable name="personen" select="normalize-space(string-join(.//text()[not(parent::tei:roleName)], ''))" />
       <xsl:variable name="personen2" select="normalize-space(string-join(.//text()[not(parent::tei:surname)], ''))" />

  <h1 class="title">Personenregister</h1>
<body>
                              <ul> 

       <xsl:for-each-group select="$collection2" group-by=".">
         <xsl:sort select="string()" order="ascending"/>
          <xsl:sort select="tei:surname" order="ascending"/>
          <xsl:sort select="tei:rolename" order="ascending"/>
          <xsl:sort select="tei:forename" order="ascending"/> 
<xsl:variable name="personen" select="normalize-space(string-join(.//text()[not(parent::tei:roleName)], ''))" />
       <xsl:variable name="personen2" select="normalize-space(string-join(.//text()[not(parent::tei:surname)], ''))" />
       <xsl:choose>
           <xsl:when test="@key">
               <xsl:choose>
                   <xsl:when test="exists(tei:roleName)"><a href="{@key}" target="_blank"><xsl:value-of select="concat($personen, ', ', tei:roleName)"                    /></a></xsl:when>
                   <xsl:when test="exists(tei:surname)" ><a href="{@key}" target="_blank"><xsl:value-of select="concat($personen2, ', ', tei:surname, ', ', tei:roleName)"/></a></xsl:when>
                   <xsl:otherwise><a href="{@key}" target="_blank"><xsl:value-of select="$personen"/></a></xsl:otherwise>
               </xsl:choose>
           </xsl:when>
           <xsl:otherwise>
               <xsl:choose>
                   <xsl:when test="exists(tei:roleName)"><xsl:value-of select="concat($personen, ', ', tei:roleName)"/></xsl:when>
                   <xsl:otherwise><xsl:value-of select="$personen"/></xsl:otherwise>
               </xsl:choose>
           </xsl:otherwise>
       </xsl:choose>
与“Herr”和“Herrn”(先生)的事情: 我只想拥有姓氏,姓名和头衔,但没有先生或夫人(赫尔)。所以我想在我的persName

中删除“Herr”

1 个答案:

答案 0 :(得分:1)

这是您的XSLT的修订版。它几乎是一个精确的副本,但有一些结构修改:

<xsl:stylesheet version="2.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tei="http://uri.com/goes/here">
    <xsl:template match="/">
        <html>
           <head>
                <link rel="stylesheet" type="text/css" href="persName.css"/>
                <title>Personenregister</title>
            </head>
            <body>
                <h1 class="title">Personenregister</h1>
                <ul> 
                    <xsl:apply-templates select="collection('./?select=*_ML.xml')//tei:persName[not(.=preceding-sibling::node())]">
                        <xsl:sort select="string()" order="ascending"/>
                    </xsl:apply-templates>
                </ul>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="tei:persName">
        <xsl:message>
            <xsl:text>in template</xsl:text>
        </xsl:message>
        <li class="liste"> 
           <xsl:variable name="personen" select="normalize-space(string-join(.//text()[not(parent::tei:roleName)], ''))" />
           <xsl:variable name="personen2" select="normalize-space(string-join(.//text()[not(parent::tei:surname)], ''))" />
           <xsl:choose>
               <xsl:when test="@key">
                   <xsl:choose>
                       <xsl:when test="exists(tei:roleName)"><a href="{@key}" target="_blank"><xsl:value-of select="concat($personen, ', ', tei:roleName)"                    /></a></xsl:when>
                       <xsl:when test="exists(tei:surname)" ><a href="{@key}" target="_blank"><xsl:value-of select="concat($personen2, ', ', tei:surname, ', ', tei:roleName)"/></a></xsl:when>
                       <xsl:otherwise><a href="{@key}" target="_blank"><xsl:value-of select="$personen"/></a></xsl:otherwise>
                   </xsl:choose>
               </xsl:when>
               <xsl:otherwise>
                   <xsl:choose>
                       <xsl:when test="exists(tei:roleName)"><xsl:value-of select="concat($personen, ', ', tei:roleName)"/></xsl:when>
                       <xsl:otherwise><xsl:value-of select="$personen"/></xsl:otherwise>
                   </xsl:choose>
               </xsl:otherwise>
           </xsl:choose>
        </li>
    </xsl:template>
</xsl:stylesheet>

最大的变化发生在这里:

<xsl:apply-templates select="collection('./?select=*_ML.xml')//tei:persName[not(.=preceding-sibling::node())]">
    <xsl:sort select="string()" order="ascending"/>
</xsl:apply-templates>

这是选择所有组件文件的更好方法。 XPath函数collection('./?select=*_ML.xml')将选择工作路径中与*_ML.xml匹配的所有文件,并将该组文件转换为一组节点。然后,我们选择所有persName元素的集合。

然后,要仅选择不同的persName元素,我们应用谓词:not(.=preceding-sibling::node())。此谓词声明忽略与我们已经处理的节点具有相同内容的所有节点。这要求节点完全相同,因此如果过于严格,您可以修改谓词以满足您的需求。

在此之后,我们按字母顺序对节点进行排序。您可以在apply-templates指令中执行此操作。您还可以包含多个sort指令以对多个字段进行排序(当然,您需要将以下select语句替换为实际语句):

<xsl:sort select="surname" order="ascending"/>
<xsl:sort select="rolename" order="ascending"/>
<xsl:sort select="forename" order="ascending"/>

我认为这就是你要求的一切......嗯......好吧就是这样:

  

但我不知道如何删除有时出现在我的persName中的“Herr”或“Herrn”。你知道怎么做的吗?

给我们举个例子,因为我不是100%肯定你的意思。什么时候有时看起来不应该?

P.S。这是我的测试的示例输出,以显示它正在运行:

发件人

**01_ML.xml:**
<persName xmlns="http://uri.com/goes/here" role="addressee">Herr <roleName>Prof. Dr.</roleName>XYY</persName>

**02_ML.xml:**
<TEI xmlns="http://uri.com/goes/here">
    <persName key="linktodatabank">Herr <roleName>Dr.</roleName> Hugo <surname>Muller</surname></persName>

    <persName>Herr Heinz</persName>
    <persName>Herr Heinz</persName>
    <persName>Herr Heinz</persName>
    <persName>Herr Heinz</persName>
    <persName>Herr Heinz</persName>
    <persName>Herr Heinz</persName>
    <persName>Herr Heinz</persName>
    <persName>Herr Heinz</persName>
    <persName>Volkm</persName>
</TEI>

<?xml version="1.0" encoding="UTF-8"?><html xmlns="http://www.w3.org/1999/xhtml" xmlns:tei="http://uri.com/goes/here">
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      <link rel="stylesheet" type="text/css" href="persName.css" />
      <title>Personenregister</title>
   </head>
   <body>
      <h1 class="title">Personenregister</h1>
      <ul>
         <li class="liste"><a href="linktodatabank" target="_blank">Herr Hugo Muller, Dr.</a></li>
         <li class="liste">Herr Heinz</li>
         <li class="liste">Herr XYY, Prof. Dr.</li>
         <li class="liste">Volkm</li>
      </ul>
   </body>
</html>