0

我有以下 XML 文档:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Entity Type="defect">
  <Fields>
    <Field Name="user-28"/>
    <Field Name="user-29">
      <Value>1</Value>
    </Field>
    <Field Name="has-change">
      <Value></Value>
    </Field>
    ...

我正在尝试对其进行转换,以便所有Field元素都成为Name属性转换为元素的元素,并且它会删除该Fields元素。到目前为止,我使用以下转换取得了部分成功:

<?xml version="1.0" encoding="UTF-8"?>
<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:template match="//Entity">
    <xsl:copy>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="Field">
    <xsl:element name="{@Name}">
      <xsl:value-of select="Value"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

它导致以下结果,部分正确,但它丢失了元素的Type属性:Entity

<?xml version="1.0" encoding="UTF-8"?>
<Entity>

    <user-28/>
    <user-29>1</user-29>
    <has-change/>

另一个复杂之处是我还需要它来处理以下文档,该文档包含一个Entities具有多个Entity节点的根节点,而不会丢失根节点:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Entities TotalResults="60">
  <Entity Type="defect">
    <Fields>
      <Field Name="id">
        <Value>1161</Value>
      </Field>
4

2 回答 2

1

<xsl:copy>仅复制节点本身,如果其属性或子节点则不复制。应用于属性,它复制完整的属性,即名称和值。

在进行保留​​大部分文档的转换时,最好使用恒等转换模板。那这个呢:

<?xml version="1.0" encoding="UTF-8"?>
<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"/>

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

  <!-- We don't want to copy <Fields>, just the contents -->
  <xsl:template match="Fields">
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="Field">
    <xsl:element name="{@Name}">
      <xsl:value-of select="Value"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>
于 2012-11-16T08:20:57.440 回答
1

你很亲密。请在下面查看我的答案中的细微变化。

当这个 XSLT 1.0 解决方案:

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

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

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

  <xsl:template match="Field">
     <xsl:element name="{@Name}">
       <xsl:value-of select="Value" />
     </xsl:element>
  </xsl:template>

</xsl:stylesheet>

...应用于第一个提供的 XML:

<?xml version="1.0" encoding="UTF-8"?>
<Entity Type="defect">
  <Fields>
    <Field Name="user-28"/>
    <Field Name="user-29">
      <Value>1</Value>
    </Field>
    <Field Name="has-change">
      <Value/>
    </Field>
    <!-- other <Field> elements -->
  </Fields>
</Entity>

...产生了想要的结果:

<?xml version="1.0"?>
<Entity Type="defect">
  <user-28 />
  <user-29>1</user-29>
  <has-change />
  <!-- other <Field> elements -->
</Entity>

如果针对第二个提供的 XML 运行相同的 XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<Entities TotalResults="60">
  <Entity Type="defect">
    <Fields>
      <Field Name="id">
        <Value>1161</Value>
      </Field>
      <!-- other <Field> elements -->
    </Fields>
  </Entity>
</Entities>

...再次,产生了想要的结果:

<?xml version="1.0"?>
<Entities TotalResults="60">
  <Entity Type="defect">
    <id>1161</id>
    <!-- other <Field> elements -->
  </Entity>
</Entities>

解释:

  • 第一个模板是The Identity Transform. 正如您可能推测的那样,它的目的是默认情况下将源文档中的所有节点和属性原样复制到结果文档中。
  • 第二个模板匹配所有<Fields>元素。找到一个后,XSLT 解析器被指示将模板应用到其子元素(另外,它具有删除该<Fields>元素的效果)。
  • 最终模板与您已有的模板相同。
于 2012-11-16T08:21:22.067 回答