5

编辑 -我已经找到了解决问题的方法,并在此处 发布了问答。

我正在寻求处理符合美国国会图书馆 EAD 标准(在此处找到)的 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>。它可能被 a<descgrp>或 a<bioghist>或其组合包裹。我不能select="//bioghist",因为那会拉出所有标签<bioghist>。我什至不能,select="//bioghist[1]"因为那里实际上可能没有<bioghist>标签,然后我将拉下面的值<c01>,这是“第二”,应该稍后处理。

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

我喜欢说什么

  • 获取<bioghist>当前节点下方任意位置的任何标签,但
  • <c??>如果您点击标签,请不要深入挖掘

我希望我已经把情况说清楚了。如果我留下任何模棱两可的地方,请告诉我。您能提供的任何帮助将不胜感激。谢谢。

4

2 回答 2

2

由于要求相当模糊,任何答案都只能反映其作者所做的猜测。

这是我的:

<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>
于 2012-06-28T03:39:44.127 回答
0

我自己制定了一个解决方案并将其发布在此问答中,因为该解决方案非常特定于某个 XML 标准,并且似乎超出了此问题的范围。如果人们认为最好也将其发布在这里,我可以使用副本更新此答案。

于 2012-07-11T18:38:08.697 回答