我有以下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>
答案 0 :(得分:1)
<xsl:copy>
仅复制节点本身,如果其属性或子节点则为none。应用于属性,它复制完整的属性,即名称和值。
在进行保留大部分文档的转换时,最好使用身份转换模板。那怎么样:
<?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>
答案 1 :(得分: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>
元素的效果)。