XSLT 将来自多个节点的属性连接成单个值

Posted

技术标签:

【中文标题】XSLT 将来自多个节点的属性连接成单个值【英文标题】:XSLT to concat attributes from multiple nodes into a single value 【发布时间】:2021-10-31 13:11:09 【问题描述】:

我想创建一个接受node 参数的XSLT 1.0 模板。该模板将连接每个节点的@lot@plan_type@plan 属性,用逗号连接每个节点结果并输出一个字符串。请参阅下面的示例 XML。

<?xml version="1.0" encoding="UTF-8"?>
<RealEstate unique_id="045dcd20-0a69-4f2a-9bfa-c6b3e9b03281">
    <Title id="23bccbb0-2699-44bf-a672-9d2a27344254"
        instruction_id="10752681" is_primary="Yes" lot="184" plan="1212069"
        plan_type="DepositedPlan" tenure_type="Freehold" type="Torrens" />
    <Title id="045dcd20-0a69-4f2a-9bfa-c6b3e9b03281"
        instruction_id="10752681" is_primary="No" lot="185" plan="1212073"
        plan_type="DepositedPlan" tenure_type="Freehold" type="Torrens" />
    <Title id="c6b3e9b0-4f2a-44bf-a672-23bccbb04254"
        instruction_id="10752681" is_primary="No" lot="186" plan="1213002"
        plan_type="DepositedPlan" tenure_type="Freehold" type="Torrens" />
</RealEstate>

Title 节点将被传递给node 参数。然后将循环每个Title 节点以构建和输出字符串Lot 184 DepositedPlan 1212069, Lot 185 DepositedPlan 1212073, Lot 186 DepositedPlan 1213002

【问题讨论】:

好吧,你试过什么?像Title 这样的元素节点实际上是使用路径Title 选择的,名为lot 的属性是使用@lot 选择的,正如您已经展示的那样,连接值的函数被命名为concat,那么您在哪里卡住了? 我看不出参数在这里扮演什么角色。您是否希望 Title 以外的元素具有相同的属性? 感谢马丁和迈克尔。参数的作用是使模板可以内联用作更大模板的一部分,并在 Altova MapForce 设计中“映射”输入和输出。 它也会更通用,因此如果将具有@lot@plan@plan_type 属性的&lt;LandParcel /&gt; 节点传递给模板,则输出将是相同的。 您使用哪个版本的 XSLT? 【参考方案1】:

在 XSLT 2 及更高版本中我会使用

  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:apply-templates select="//Title"/>
  </xsl:template>
  
  <xsl:template match="Title">
    <xsl:if test="position() > 1">, </xsl:if>
    <xsl:value-of select="@lot, @plan_type, @plan" separator=" "/>
  </xsl:template>

在 XSLT 1 中,最后一个模板是

  <xsl:template match="Title">
    <xsl:if test="position() > 1">, </xsl:if>
    <xsl:value-of select="concat(@lot, ' ', @plan_type, ' ', @plan)"/>
  </xsl:template>

【讨论】:

【参考方案2】:

如果您想要一个通用模板,可以从作为参数传递给它的元素中提取属性,请尝试以下操作:

XSLT 1.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" />

<xsl:template match="/RealEstate">
    <xsl:call-template name="get-attributes">
        <xsl:with-param name="elements" select="Title"/>
    </xsl:call-template>
</xsl:template>

<xsl:template name="get-attributes">
    <xsl:param name="elements" select="/.."/>
    <xsl:variable name="elem" select="$elements[1]" />
    <!-- output -->
    <xsl:value-of select="$elem/@lot"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="$elem/@plan_type"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="$elem/@plan"/>
    <!-- continue -->
    <xsl:if test="count($elements) > 1">
        <xsl:text>, </xsl:text>
        <!-- recursive call -->
        <xsl:call-template name="get-attributes">
            <xsl:with-param name="elements" select="$elements[position() > 1]"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>   

应用于您的输入示例,这将产生:

结果

184 DepositedPlan 1212069, 185 DepositedPlan 1212073, 186 DepositedPlan 1213002

请注意,传递给命名模板的参数是节点集,而不是字符串

【讨论】:

优雅的解决方案和一些摆弄应该能够满足我的需求。我很乐意聘请您的专业知识,因为我需要进一步的 XSLT 模板作为我正在从事的项目的一部分的功能。请联系evosys.com.au/contact 我给你发了我的电子邮件。

以上是关于XSLT 将来自多个节点的属性连接成单个值的主要内容,如果未能解决你的问题,请参考以下文章

XSLT 1.0 将同一级别的多个相同节点以不同的值分组

使用 xslt 将 xml 复杂节点元素拆分为多个节点

XSLT:如何将一个元素解析为多个变量

XSLT将同名兄弟节点的值合并/连接到单个节点中

使用 XSLT 将 XML 转换为 CSV,用于在单个标记中以空格分隔的多个记录

将多个 csv 文件连接成具有相同标题的单个 csv - Python