如何在 XSLT 条件下更改硬编码元素的位置?

Posted

技术标签:

【中文标题】如何在 XSLT 条件下更改硬编码元素的位置?【英文标题】:How to change position of hardcoded elements on condition in XSLT? 【发布时间】:2021-10-30 02:17:26 【问题描述】:

我正在编写一个模板并调用该特定模板,并且我正在硬编码一些新元素,我希望我的 xslt 中的这些硬编码元素按照下面我想要的输出中所示的顺序显示在结果输出中。这个条件怎么写?

这是我的输入请求:

<companies>
  <company>
    <locations>
      <location>
        <ID>1</ID>
        <empdetails>
          <empdetail>
            <x>A</x>
            <y>B</y>
          </empdetail>
        </empdetails>
        <empdetails>
          <empdetail>
            <x>A1</x>
            <y>B1</y>
          </empdetail>
        </empdetails>     
      </location>
    </locations>
    <locations>
      <location>
        <ID>2</ID>
        <empdetails>
          <empdetail>
            <x>A2</x>
            <y>B2</y>
          </empdetail>
        </empdetails>
        <empdetails>
          <empdetail>
            <x>A3</x>
            <y>B3</y>
          </empdetail>
        </empdetails>
      </location>
    </locations>
  </company>
</companies>

这是所需的输出:

<employeeinfo>
  <employees>
    <employee>
      <ID>1</ID>
      <details>
        <detail>
          <A>A</A>
          <B>B</B>
        </detail>
      </details>
      <details>
        <detail>
          <A>A1</A>
          <B>B1</B>
        </detail>
      </details>
    </employee>
  </employees>
  <employees>
    <employee>
      <ID>2</ID>
      <details>
        <detail>
          <A>A2</A>
          <B>B2</B>
        </detail>
      </details>
      <details>
        <detail>
          <A>A3</A>
          <B>B3</B>
        </detail>
      </details>
    </employee>
  </employees>
</employeeinfo>

我得到的输出:

    <employeeinfo>
    <employees>
    <employee>
      <ID>1</ID>
      <details>
      <detail>
        <A>A</A>
        <B>B</B>
     </detail>
    </details>
    </employee>
    </employees>
    <employees>
    <employee>
     <ID>1</ID>
    <details>
      <detail>
        <A>A1</A>
        <B>B1</B>
     </detail>
    </details>
    </employee>
    </employees>
    <employees>
    <employee>
     <ID>2</ID>
    <details>
      <detail>
        <A>A2</A>
        <B>B2</B>
     </detail>
    </details>
    </employee>
    </employees>
    <employees>
    <employee>
     <ID>2</ID>
    <details>
      <detail>
        <A>A3</A>
        <B>B3</B>
     </detail>
    </details>
    </employee>
    </employees>
    </employeeinfo>

这就是我编写 XSLT 的方式:

<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" 
    indent="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:template match="companies">
    <employeeinfo>  
      <employees>
        <xsl:for-each select="//*[local-name()=locations]/*[local-name()=location]/*[local-name()=empdetails]">
          <xsl:call-template name="locations">
            <xsl:with-param name="employee" select="."/>
            
          </xsl:call-template>
        </xsl:for-each>
      </employees>
    </employeeinfo>
  </xsl:template>
  <xsl:template name="locations">
    <xsl:param name="employee"/>
    <xsl:variable name="A" select=".//empdetail/x"/>
    <xsl:variable name="B" select=".//empdetail/y"/>
    <xsl:variable name="C" select="../locations/ID"/>
    <employee>
      <ID>
        <xsl:value-of select="$C"/>
      </ID>
      <details>
        <detail>
          <A>
            <xsl:value-of select="$A"/>
          </A>
          <B>
            <xsl:value-of select="$B"/>
          </B>
        </detail>
      </details>
    </employee>
  </xsl:template>
</xsl:stylesheet>

【问题讨论】:

你能帮我们缩进输入和输出样本,让我们看到嵌套吗? 很抱歉我是 XSLT 的新手。怎么办? 好吧,如果您不知道如何使用 XSLT,那么请使用任何漂亮的打印机、缩进器而不是 XSLT,只需尝试让不熟悉文档类型的其他人能够以某种方式阅读输入您正在展示并尝试处理。 我将缩进 XML 文件。这很棘手,因为 OP 将 TABS 包含在其中,弄乱了缩进。我将使用外部实用程序。 【参考方案1】:

我认为您几乎想要一对一的映射,只跳过一个元素:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="companies">
    <employeeinfo>
        <xsl:apply-templates/>
    </employeeinfo>
</xsl:template>

<xsl:template match="company">
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="locations">
    <employees>
        <xsl:apply-templates/>
    </employees>
</xsl:template>

<xsl:template match="location">
    <employee>
        <xsl:apply-templates/>
    </employee>
</xsl:template>

<xsl:template match="empdetails">
    <details>
        <xsl:apply-templates/>
    </details>
</xsl:template>

<xsl:template match="empdetail">
    <detail>
        <xsl:apply-templates/>
    </detail>
</xsl:template>

<xsl:template match="x">
    <A>
        <xsl:apply-templates/>
    </A>
</xsl:template>

<xsl:template match="y">
    <B>
        <xsl:apply-templates/>
    </B>
</xsl:template>

</xsl:stylesheet>

【讨论】:

可悲的是我不能在我的 xslt 中使用模板匹配。它不工作。 如果输入与发布的一样,则显示的代码确实有效。如果输入有任何您未能显示的命名空间声明,则在您的问题和输出中编辑输入以显示任何命名空间声明。还要说明您是否使用或可以使用 XSLT 2 或 3 处理器。 输入或输出没有变化。但我不能在 xslt 中间使用 祝你好运,但不要假装你想使用 XSLT。 不要告诉我们它“不起作用”,告诉我们它是如何失败的,并更详细地告诉我们你是如何运行它的。代码是正确的,更改它以避免使用xsl:template 并不能解决您的问题,因为您误诊了问题。

以上是关于如何在 XSLT 条件下更改硬编码元素的位置?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用相对路径在 XSLT 中引用 CSS

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

如何使用 XSLT 替换 XML 节点名称中的字符 - 更改根元素

使用 Python 或 XSLT 将复杂的 XML 转换为 CSV

删除 C# 中重复的硬编码循环和条件

如何仅在 phpunit 测试中更改硬编码的 Eloquent $connection?