编辑-
我已经找到解决问题的方法,并发布了一个问答here

我正在寻找符合国会图书馆EAD标准(找到here)的XML。不幸的是,该标准在XML结构方面过于宽松。

例如,<bioghist>标记可以存在于<archdesc>标记内或<descgrp>标记内,或嵌套在另一个<bioghist>标记内,或上述两者的组合,或者可以完全省略。我发现很难只选择我要寻找的生物标记,而不选择其他标记。

以下是XSLT可能需要处理的一些不同的EAD XML文档:

第一个例子

<ead>
<eadheader>
    <archdesc>
        <bioghist>one</bioghist>
        <dsc>
            <c01>
                <descgrp>
                    <bioghist>two</bioghist>
                </descgrp>
                <c02>
                    <descgrp>
                        <bioghist>
                            <bioghist>three</bioghist>
                        </bioghist>
                    </descgrp>
                </c02>
            </c01>
        </dsc>
    </archdesc>
</eadheader>
</ead>

第二个例子
<ead>
<eadheader>
    <archdesc>
        <descgrp>
            <bioghist>
                <bioghist>one</bioghist>
            </bioghist>
        </descgrp>
        <dsc>
            <c01>
                <c02>
                    <descgrp>
                        <bioghist>three</bioghist>
                    </descgrp>
                </c02>
                <bioghist>two</bioghist>
            </c01>
        </dsc>
    </archdesc>
</eadheader>
</ead>

第三个例子
<ead>
<eadheader>
    <archdesc>
        <descgrp>
            <bioghist>one</bioghist>
        </descgrp>
        <dsc>
            <c01>
                <c02>
                    <bioghist>three</bioghist>
                </c02>
            </c01>
        </dsc>
    </archdesc>
</eadheader>
</ead>

如您所见,EAD XML文件几乎在任何地方都可能带有<bioghist>标记。我想产生的实际输出太复杂,无法在此处发布。以上三个EAD示例的输出的简化示例可能类似于:

第一个示例的输出
<records>
<primary_record>
    <biography_history>first</biography_history>
</primary_record>
<child_record>
    <biography_history>second</biography_history>
</child_record>
<granchild_record>
    <biography_history>third</biography_history>
</granchild_record>
</records>

第二个示例的输出
<records>
<primary_record>
    <biography_history>first</biography_history>
</primary_record>
<child_record>
    <biography_history>second</biography_history>
</child_record>
<granchild_record>
    <biography_history>third</biography_history>
</granchild_record>
</records>

第三个示例的输出
<records>
<primary_record>
    <biography_history>first</biography_history>
</primary_record>
<child_record>
    <biography_history></biography_history>
</child_record>
<granchild_record>
    <biography_history>third</biography_history>
</granchild_record>
</records>

如果要提取“第一个”生物特征值并将其放入<primary_record>,则不能简单地使用<xsl:apply-templates select="/ead/eadheader/archdesc/bioghist",因为该标记可能不是<archdesc>标记的直接后代。它可以用<descgrp><bioghist>或其组合包装。而且我不能select="//bioghist",因为那样会拉所有<bioghist>标记。我什至没有select="//bioghist[1]",因为那里可能实际上没有<bioghist>标记,然后我将值拉到<c01>下面,该值为“Second”,应稍后处理。

这已经是一篇很长的文章了,但是另一个麻烦是,可以有无限数量的<cxx>节点,最多嵌套十二层。我目前正在递归处理它们。我尝试将当前正在处理的节点(例如<c01>)保存为名为“RN”的变量,然后运行<xsl:apply-templates select=".//bioghist [name(..)=name($RN) or name(../..)=name($RN)]">。这适用于某些形式的EAD,其中<bioghist>标签没有嵌套得太深,但是如果必须处理由喜欢将标签包裹在其他标签中的人创建的EAD文件,则它将失败(根据EAD标准)。

我最想说的是
  • 在当前节点下方但
  • 下方的任何位置获取任何<bioghist>标记
  • 如果您打了<c??>标签
  • ,请不要更深入地研究

    我希望我已经把情况弄清楚了。如果我有任何歧义,请告诉我。您可以提供的任何帮助将不胜感激。谢谢。

    最佳答案

    由于要求相当模糊,因此任何答案都只能反射(reflect)其作者的猜测。

    这是我的:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:my="my:my" exclude-result-prefixes="my">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <my:names>
      <n>primary_record</n>
      <n>child_record</n>
      <n>grandchild_record</n>
     </my:names>
    
     <xsl:variable name="vNames" select="document('')/*/my:names/*"/>
    
     <xsl:template match="/">
      <xsl:apply-templates select=
       "//bioghist[following-sibling::node()[1]
                                    [self::descgrp]
                  ]"/>
     </xsl:template>
    
     <xsl:template match="bioghist">
      <xsl:variable name="vPos" select="position()"/>
    
      <xsl:element name="{$vNames[position() = $vPos]}">
       <xsl:value-of select="."/>
      </xsl:element>
     </xsl:template>
    
     <xsl:template match="text()"/>
    </xsl:stylesheet>
    

    在提供的XML文档上应用此转换时:
    <ead>
        <eadheader>
            <archdesc>
                <bioghist>first</bioghist>
                <descgrp>
                    <bioghist>first</bioghist>
                    <bioghist>
                        <bioghist>first</bioghist></bioghist>
                </descgrp>
                <dsc>
                    <c01>
                        <bioghist>second</bioghist>
                        <descgrp>
                            <bioghist>second</bioghist>
                            <bioghist>
                                <bioghist>second</bioghist></bioghist>
                        </descgrp>
                        <c02>
                            <bioghist>third</bioghist>
                            <descgrp>
                                <bioghist>third</bioghist>
                                <bioghist>
                                    <bioghist>third</bioghist></bioghist>
                            </descgrp>
                        </c02>
                    </c01>
                </dsc>
            </archdesc>
        </eadheader>
    </ead>
    

    产生想要的结果:
    <primary_record>first</primary_record>
    <child_record>second</child_record>
    <grandchild_record>third</grandchild_record>
    

    10-06 07:27