编辑-
我已经找到解决问题的方法,并发布了一个问答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>