【问题标题】:Use tags from input as enclosing tags in XSLT XML output使用输入中的标签作为 XSLT XML 输出中的封闭标签
【发布时间】:2022-01-23 19:29:36
【问题描述】:

我有一些 XML(我无法控制),其中包含一些“rdf”注释。 我正在尝试将其转换为实际可用的 RDF/XML(使用 XSLT),但有一个问题我不太知道如何解决。 首先,在 XML 中有很长的部分,如下所示:

<rdf:Description>
  <some:tag>
    <rdf:Bag>
      <rdf:li rdf:resource="resource1" />
    </rdf:Bag>
  </some:tag>
  <some:other-tag>
    <rdf:Bag>
      <rdf:li rdf:resource="resource2" />
      <rdf:li rdf:resource="resource3" />
    </rdf:Bag>
  </some:other-tag>
</rdf:Description>

目标是像这样创建 RDF/XML:

<rdf:Description>
  <some:tag>resource1</some:tag>
  <some:other-tag>resource2<some:other-tag>
  <some:other-tag>resource3<some:other-tag>
</rdf:Description>

然而,不同标签的数量可能是无限的,所以我不能在这里列举不同的情况。我需要一些通用的方法来使用包周围的标签作为各个资源属性的封闭标签。

很遗憾,我对 XSLT 真的不太了解,所以在这里不知所措。

不幸的是,到目前为止我所做的不适用于some:other-tag 的情况,因为我只得到一个三元组,其中对象是连接的: &lt;some:other-tag&gt;resource2resource3&lt;/some:other-tag&gt;

  <xsl:template match="rdf:Description/*">
    <xsl:copy>
      <xsl:for-each select="rdf:Bag/rdf:li/@rdf:resource">
        <xsl:value-of select="."/>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

【问题讨论】:

    标签: xml xslt rdf


    【解决方案1】:

    我将从身份转换模板开始(例如,在 XSLT 3 中,只需声明 &lt;xsl:mode on-no-match="shallow-copy"/&gt;),然后添加两个模板

      <xsl:template match="*[rdf:Bag]| rdf:Bag">
        <xsl:apply-templates/>
      </xsl:template>
      
      <xsl:template match="rdf:Bag/rdf:*">
        <xsl:element name="{name(../..)}" namespace="{namespace-uri(../..)}">{@rdf:resource}</xsl:element>
      </xsl:template>
    

    这应该给出例如

    <rdf:Description xmlns:rdf="http://example.com/rdf" xmlns:some="http://example.com/some">
       <some:tag>resource1</some:tag>
       <some:other-tag>resource2</some:other-tag>
       <some:other-tag>resource3</some:other-tag>
    </rdf:Description>
    

    对于像这样的输入

    <rdf:Description xmlns:rdf="http://example.com/rdf" xmlns:some="http://example.com/some">
      <some:tag>
        <rdf:Bag>
          <rdf:li rdf:resource="resource1" />
        </rdf:Bag>
      </some:tag>
      <some:other-tag>
        <rdf:Bag>
          <rdf:li rdf:resource="resource2" />
          <rdf:li rdf:resource="resource3" />
        </rdf:Bag>
      </some:other-tag>
    </rdf:Description>
    

    您没有真正展示命名空间,也没有告诉我们除了rdf:Bar 之外是否还有其他元素,如果有,它们需要如何转换。

    【讨论】:

    • 使用 xsltproc/XSLTv1 我不得不将{@rdf:resource} 换成&lt;xsl:value-of select="@rdf:resource" /&gt;
    【解决方案2】:

    好的,我想出了一种将其编写为递归过程的方法。如果有人过来告诉我有一个更干净、更惯用的版本,我仍然会很高兴,但是,如果这可能对某人有所帮助,那就给你吧:

    
      <xsl:template name="bonkers">
        <xsl:param name="rs" required="yes"/>
        <xsl:copy copy-namespaces="no">
          <xsl:value-of select="subsequence($rs, 1, 1)"/>
        </xsl:copy>
        <xsl:if test="false() = empty($rs)">
          <xsl:call-template name="bonkers">
            <xsl:with-param name="rs" select="subsequence($rs, 2)"/>
          </xsl:call-template>
        </xsl:if>
      </xsl:template>
    
      <xsl:template match="rdf:Description/*">
        <xsl:variable name="resources" select="rdf:Bag/rdf:li/@rdf:resource"/>
        <xsl:call-template name="bonkers">
          <xsl:with-param name="rs" select="$resources"/>
        </xsl:call-template>
      </xsl:template>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多