使用 XSLT 1.0 进行多项更改(大写元素首字母、顺序元素、聚合/组元素)

Posted

技术标签:

【中文标题】使用 XSLT 1.0 进行多项更改(大写元素首字母、顺序元素、聚合/组元素)【英文标题】:Make multiple changes with XLST 1.0 (uppercase element first letter, order elements, aggrate/group elements) 【发布时间】:2021-02-23 20:48:59 【问题描述】:

我的输入 xml 看起来像这样:

<myFamily>
  <spouse type="1">Halle Berry</spouse>
  <parent type="bio">Jane Smith-Doe</parent>
  <spouse type="2">Eva Longoria</spouse>
  <uncle type="paternal">Bob Beam</uncle>
  <parent type="bio">Jim Beam</parent>
  <uncle type="maternal">Mike Smith</uncle>
  <aunt type="paternal">Viola Davis</aunt>
  <inLaw type="mother">Dr. Curry-Pepper</inLaw>
  <brother name="Ron Isley">
    <child>Sara Isley</child>
    <child>Ron Isley Jr.</child>
    <child>Martha Isley-Focker</child>
  </brother>
  <parent type="step">Jon Doe</parent>
  <inLaw type="father">Dr. Pepper</inLaw>
  <spouse type="3">Sofia Vergara</spouse>
  <uncle type="paternal">Bo Beam</uncle>
  <spouse type="3">Sonya Curry</spouse>
  <Sister name ="Shelly Isley"/>
</myFamily>

我希望它以这样的方式结束:

<MyFamily>
  <Parents>
    <Parent type="bio">Jane Smith-Doe</Parent>
    <Parent type="bio">Jim Beam</Parent>
    <Parent type="step">Jon Doe</Parent>
  </Parents>
  <Siblings>
    <Sister name ="Shelly Isley"/>
    <Brother name="Ron Isley">
      <Child>Sara Isley</Child>
      <Child>Ron Isley Jr.</Child>
      <Child>Martha Isley-Focker</Child>
    </Brother>
  <Siblings>
  <Uncles>
    <Uncle type="paternal">Bob Beam</Uncle>
    <Uncle type="maternal">Mike Smith</Uncle>
    <Uncle type="paternal">Bo Beam</Uncle>  
  </Uncles>
  <Aunts><Aunt type="paternal">Viola Davis</Aunt><Aunts>
  <InLaws>
    <InLaw type="mother">Dr. Curry-Pepper</InLaw>
    <InLaw type="father">Dr. Pepper</InLaw>
  </InLaws>
  <Wives>
    <Wife type="1">Halle Berry</Wife>
    <Wife type="2">Eva Longoria</Wife>
    <Wife type="3">Sofia Vergara</Wife>
    <Wife type="3">Sonya Curry</Wife>
  </Wives>
</MyFamily>

要使第一个字母大写,重命名配偶,并以某种方式排序我试过这个,但没有用:

<xsl:template match="@*|node()">
    <xsl:copy>
        <!-- Order Section Nodes -->
        <xsl:apply-templates select="myFamily[(SectionName = 'parent')]" mode="nodeCopy"/>
        <xsl:apply-templates select="myFamily[(SectionName = 'sister')]" mode="nodeCopy"/>
        <xsl:apply-templates select="myFamily[(SectionName = 'brother')]" mode="nodeCopy"/>
        <xsl:apply-templates select="myFamily[(SectionName = 'unle')]" mode="nodeCopy"/>
        <xsl:apply-templates select="myFamily[(SectionName = 'aunt')]" mode="nodeCopy"/>
        <xsl:apply-templates select="myFamily[(SectionName = 'inLaw')]" mode="nodeCopy"/>
        <xsl:apply-templates select="myFamily[(SectionName = 'spouse')]" mode="nodeCopy"/>
        <!-- List All Remaining Nodes and Remove ones that have already been ordered above -->
        <xsl:apply-templates select="@*|node()[not(parent | sister | brother |  spouse | uncle | aunt | inLaw)]"/>
  </xsl:copy>
</xsl:template>
<!-- Rename spouse Nodes -->
<xsl:template match="spouse">
  <Wife><xsl:apply-templates select="@*|node()" mode="nodeCopy"/></Wife>
</xsl:template>
<!-- Uppercase first letter of elements -->
<xsl:template match="*">
  <xsl:element name="concat(
                        translate(subsstring(name(.),1,1), $vLower, $vUpper),
                        substring(name(.), 2, string-length(name(.))-1)
                      )">
    <xsl:apply-templates select="@*|node()"/>
  </xsl:element>
</xsl:template>

关于我想要分组的方式,我觉得这可能适用(https://***.com/a/16818842/5517100),但我不明白。老实说,我几乎看不懂。

【问题讨论】:

请一次问一个问题。 WRT 了解 XSLT 1.0 分组,建议您阅读:jenitennison.com/xslt/grouping/muenchian.html。尽管使用预定义的组,您可能不需要它。 由于标题大小写不匹配(即&lt;Child&gt;Sara Isley&lt;/child&gt;),您想要的结果格式不正确。请记住 XML 区分大小写。为什么是&lt;Aunt&gt; 标题大小写而不是&lt;uncle&gt;?您正在寻找的解决方案的通用性如何?配偶永远是妻子吗?为什么不只通过那些根部分(即所有父母、所有兄弟姐妹等)检索节点?这感觉像是一个课程作业问题。 哎呀....意味着 em 匹配大写。这是一个剪切和粘贴失败 【参考方案1】:

使用示例中所示的预定义组,您可以简单地执行以下操作:

<xsl:template match="/myFamily">
    <MyFamily>
        <Parents>
            <xsl:apply-templates select="parent"/>
        </Parents>
        <Siblings>
            <xsl:apply-templates select="brother | sister"/>
        </Siblings>
        
        <!-- continue for other groups -->
        
    </MyFamily>
</xsl:template>

或者,如果您希望省略空组:

<xsl:template match="/myFamily">
    <MyFamily>
        <xsl:variable name="parents" select="parent" />
        <xsl:if test="$parents">
            <Parents>
                <xsl:apply-templates select="$parents"/>
            </Parents>
        </xsl:if>
        
        <!-- continue for other groups -->
        
    </MyFamily>
</xsl:template>

【讨论】:

这很有帮助。不敢相信我没想到。如何使嵌套元素也大写?使用这种方法的方法太多了。此答案会将 更改为 ,但不会修复 。这就是为什么我尝试用翻译来连接。不过,这还是很大的帮助。 只需添加另一个匹配 * 的模板 - 与样式表中的最后一个模板相同。

以上是关于使用 XSLT 1.0 进行多项更改(大写元素首字母、顺序元素、聚合/组元素)的主要内容,如果未能解决你的问题,请参考以下文章

XSLT 1.0 / 使用条件对每个结果进行排序

xslt 不会选择在 XSLT 转换中动态更改名称空间以进行进一步转换

Xslt根据条件规则引用另一个元素来更改元素值

使用 XSLT 对子元素进行排序

使用 XSLT 程序对具有逗号分隔值的 XML 元素进行分组

使用 CDATA 元素对 xml 中的 uuid 进行排序的 xslt 模板