仅在XSLT 1.0中复制直接子项及其属性?

时间:2017-07-21 16:12:53

标签: xslt xslt-1.0

输入XML:

<root>
  <recordList>
    <record priref="1">
      <Group attr="val">
        <Field1>Value X</Field1>
        <Field2>
          <value lang="en-US">Foo</value>
          <value lang="de-DE">Bar</value>
        </Field2>
      </Group>
      <Field3 attr="val">Value Y</Field3>
    </record>
    <record priref="2">
      <Field3 attr="val">Value Z</Field3>
    </record>
  </recordList>
</root>

所需的输出(仅具有直接子元素和属性的“浅拷贝”类型):

<root>
  <record priref="1">
    <Group attr="val" />
    <Field3 attr="val">Value Y</Field3>
  </record>
  <record priref="2">
    <Field3 attr="val">Value Z</Field3>
  </record>
</root>

还有另一种方法(例如没有for-each)来实现这个目标吗?

<xsl:template match="/">
  <root>
    <xsl:apply-templates select="root/recordList/record" />
  </root>
</xsl:template>

<xsl:template match="record">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:for-each select="*">
      <xsl:copy>
        <xsl:copy-of select="@* | text()"/>
      </xsl:copy>
    </xsl:for-each>
  </xsl:copy>
</xsl:template>

编辑:文本节点“值Y”和“值Z”实际上应该在结果中。结果中的任何地方仍然不需要“Foo”和“Bar”。

3 个答案:

答案 0 :(得分:1)

非常短的模板使用parent:: - 轴:

<xsl:template match="root|record|*[parent::record]|*[parent::record]/text()|@*">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*" />
  </xsl:copy>
</xsl:template>

<xsl:template match="text()" />

它的输出是

<?xml version="1.0"?>
<root>
  <record priref="1">
    <Group attr="val">
    </Group>
  <Field3 attr="val">Value Y</Field3></record>
  <record priref="2">
    <Field3 attr="val">Value Z</Field3>
  </record>
</root>

答案 1 :(得分:1)

一种方法是不处理任何孙子:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

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

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

    <xsl:template match="record/*/node()"/>
</xsl:transform>

答案 2 :(得分:1)

如何简单地不将模板应用于您不想要的节点?

XSLT 1.0

<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="recordList">
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="record/*">
    <xsl:copy>
        <xsl:apply-templates select="@*|text()"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>