XSLT:如何获取属于元素

时间:2018-01-24 07:51:08

标签: xml xslt

我正在尝试转换这样的数据:

<word>
   <morph type="prefix">
      <item type="txt" lang="tmy-Latn">ne-</item>
      <item type="gls" lang="en">3p.POSS-</item>
      <item type="gls" lang="tpi" />
      <item type="msa" lang="en">pro</item>
   </morph>
   <morph type="stem">
      <item type="txt" lang="tmy-Latn">waŋ</item>
      <item type="msa" lang="en">noun</item>
   </morph>
</word>
<word>
  <morph>
    <item><item type="txt" lang="tmy-Latn">lil</item>
    <item type="gls" lang="en">go</item>
    <item type="msa" lang="en">verb</item>morph>
</word>

相关因素是有一堆<morph>元素,每个元素都有各种子<item>元素。问题是,对于任何给定的文档,某些类型的项元素可能完全不存在。有些可能仅存在于某些变形元素中。如果他们在场,他们可能是空的。最后,在一个变形元素中可能会有多个相同@type的项目,但是它们的@lang属性会有所不同。

当我转换文档时,我需要一种方法来了解该特定文档中存在哪些不同的项目元素 - 即基于@type@lang的不同。因此,在上面的示例中,不同的项目将是:

  • TXT
  • GLS [@lang =&#39;恩&#39;]
  • GLS [@lang =&#39; TPI&#39;]
  • MSA

最终我希望有一个for-each循环,对每个存在的item元素说(即上面列出的4个)创建一个段落,然后通过每个morph元素,如果给定项目输出其内容,如果项目不存在,则输出任何内容或占位符文本,具体取决于项目类型。如果文档中没有项目类型,则不应该有任何段落。

我制作了一个文档,其中一切工作正常,但项目类型是硬编码的,并没有考虑到可能有多个相同类型的项目(但不同的lang)。我无法对lang进行硬编码。我这样做的方式我认为我需要完全重做它。我一直在努力从网上复制xsl:key和变量以及其他技巧的例子,但我没有得到它(我根本不知道XSLT)。

期望的输出(简化):

<word>
   <p type="txt" lang="tmy-Latn">ne-waŋ</p>
   <p type="gls" lang="en">3p.POSS-???</p>
   <p type="gls" lang="tpi>???-???</p>
   <p type="msa" lang="en">pro-noun</p>
</word>
<word>
   <p type="txt" lang="tmy-Latn">lil</p>
   <p type="gls" lang="en">go</p>
   <p type="gls" lang="tpi>???</p>
   <p type="msa" lang="en">verb</p>
</word>

请注意,每个单词中的morph元素已按项目类型/ lang合并。如果此文档中预期有四种类型的空{或item,则会插入三个问号。

基于Valdi_Bo答案的示例尝试:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" />
  <xsl:key name="itemTypes" match="//item" use="@type"/>
  <xsl:key name="items" match="//item" use="concat(@type, '/', @lang)"/>

  <xsl:variable name="keys" select="//morph/item[generate-id()=
        generate-id(key('items', concat(@type, '/', @lang))[1])]"/>

  <xsl:template match="word">
    <xsl:copy>


        <xsl:for-each select="//item[generate-id()=generate-id(key('itemTypes', @type)[1])]">
          <xsl:variable name="currentType" select="@type"/>
          <xsl:for-each select="//item[generate-id()=generate-id(key('items', concat($currentType, '/', @lang))[1])]">
                <p>
                    What do I put here?
                </p>    

          </xsl:for-each>
        </xsl:for-each>

    </xsl:copy>
  </xsl:template>
</xsl:transform>

1 个答案:

答案 0 :(得分:2)

您可以使用下面给出的脚本找到不同的项目“键”(键入/ lang)。

出于演示目的,此脚本从打印所有“源”开始 项目,按类型 lang 排序。

然后是主要部分 - 创建项目列表(具有唯一的类型 / lang 属性)。

最后一部分包含刚刚创建的列表的2个演示文稿。

  • 一个清单,
  • 2级(类型/语言)列表。

就源XML而言,我假设你的pip3 freeze元素 如XML格式所需,它们位于单个 word标记中。 这就是我的模板仅与root元素匹配的原因。

root

有关工作示例,请参阅http://xsltransform.net/6q1R79v/1

从上面的脚本中你应该使用:

  • 创建列表部分 - 创建项目列表。
  • 两个“演示”循环(或者可能只是第二个循环)到 为每种类型/语言生成所需的内容。