使用 XSLT 转换 XML - 根节点不存在
Transform XML using XSLT - Root Node not present
我有一个 XML
文件:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<File>
<Customer>
<LastName>MyLastName</LastName>
</Customer>
<Cars>
<Car>
<Color>Blue</Color>
<Model>Car2</Model>
<Year>1988</Year>
<Speed>250</Speed>
</Car>
<Car>
<Color>Green</Color>
<Model>Car3</Model>
<Year>1989</Year>
<Speed>350</Speed>
</Car>
</Cars>
</File>
我想使用 XSLT
将其转换为:
<?xml version="1.0" encoding="utf-8"?>
<File>
<Purchaser>
<Name>MyLastName</Name>
</Purchaser>
<vehicles>
<vehicle>
<vehicleColor>Blue</vehicleColor>
<vehicleModel>Car2</vehicleModel>
<vehicleYear>1988</vehicleYear>
<vehicleSpeed>250</vehicleSpeed>
</vehicle>
<vehicle>
<vehicleColor>Green</vehicleColor>
<vehicleModel>Car3</vehicleModel>
<vehicleYear>1989</vehicleYear>
<vehicleSpeed>350</vehicleSpeed>
</vehicle>
</vehicles>
</File>
我的 XSLT
文件:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"
indent="yes"
encoding="utf-8"
media-type="text/xml"/>
<xsl:template match="File/Customer">
<xsl:element name="Purchaser">
<xsl:element name="Name">
<xsl:value-of select="LastName"/>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="File/Cars">
<xsl:element name="vehicles">
<xsl:for-each select="Car">
<xsl:element name="vehicle">
<xsl:element name="vehicleColor">
<xsl:value-of select="Color"/>
</xsl:element>
<xsl:element name="vehicleModel">
<xsl:value-of select="Model"/>
</xsl:element>
<xsl:element name="vehicleYear">
<xsl:value-of select="Year"/>
</xsl:element>
<xsl:element name="vehicleSpeed">
<xsl:value-of select="Speed"/>
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
但是我的输出文件中没有根节点。如何做到这一点?
另外,这样改造好吗?多个模板堆叠在一起?
我建议从身份转换模板开始
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
它复制您不想转换的节点,例如 File
元素,然后允许您添加模板来执行转换,例如
<xsl:template match="Customer">
<Purchaser>
<xsl:apply-templates/>
</Purchaser>
</xsl:template>
<xsl:template match="LastName">
<Name>
<xsl:apply-templates/>
</Name>
</xsl:template>
<xsl:template match="Cars">
<vehicles>
<xsl:apply-templates/>
</vehicles>
</xsl:template>
<xsl:template match="Car">
<vehicle>
<xsl:apply-templates/>
</vehicle>
</xsl:template>
<xsl:template match="Car/*">
<xsl:element name="vehicle{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
等等。如您所见,我在大多数地方都简单地使用了文字结果元素,而不是更冗长的 xsl:element
,因为只有当您需要在 运行 时间计算名称 and/or 名称空间时才需要这样做.
Is this a good way to make the transformation? With several templates
stacked?
您可以使用多个模板,也可以使用一个模板 - 在这种情况下,两种方法都没有明显的优势或劣势。就个人而言,我会保持简短并坚持使用一个模板(主要是因为您只复制一个节点而无需修改):
<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="/File">
<File>
<Purchaser>
<Name>
<xsl:value-of select="Customer/LastName"/>
</Name>
</Purchaser>
<vehicles>
<xsl:for-each select="Cars/Car">
<vehicle>
<xsl:for-each select="*">
<xsl:element name="vehicle{name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</vehicle>
</xsl:for-each>
</vehicles>
</File>
</xsl:template>
</xsl:stylesheet>
我有一个 XML
文件:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<File>
<Customer>
<LastName>MyLastName</LastName>
</Customer>
<Cars>
<Car>
<Color>Blue</Color>
<Model>Car2</Model>
<Year>1988</Year>
<Speed>250</Speed>
</Car>
<Car>
<Color>Green</Color>
<Model>Car3</Model>
<Year>1989</Year>
<Speed>350</Speed>
</Car>
</Cars>
</File>
我想使用 XSLT
将其转换为:
<?xml version="1.0" encoding="utf-8"?>
<File>
<Purchaser>
<Name>MyLastName</Name>
</Purchaser>
<vehicles>
<vehicle>
<vehicleColor>Blue</vehicleColor>
<vehicleModel>Car2</vehicleModel>
<vehicleYear>1988</vehicleYear>
<vehicleSpeed>250</vehicleSpeed>
</vehicle>
<vehicle>
<vehicleColor>Green</vehicleColor>
<vehicleModel>Car3</vehicleModel>
<vehicleYear>1989</vehicleYear>
<vehicleSpeed>350</vehicleSpeed>
</vehicle>
</vehicles>
</File>
我的 XSLT
文件:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"
indent="yes"
encoding="utf-8"
media-type="text/xml"/>
<xsl:template match="File/Customer">
<xsl:element name="Purchaser">
<xsl:element name="Name">
<xsl:value-of select="LastName"/>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="File/Cars">
<xsl:element name="vehicles">
<xsl:for-each select="Car">
<xsl:element name="vehicle">
<xsl:element name="vehicleColor">
<xsl:value-of select="Color"/>
</xsl:element>
<xsl:element name="vehicleModel">
<xsl:value-of select="Model"/>
</xsl:element>
<xsl:element name="vehicleYear">
<xsl:value-of select="Year"/>
</xsl:element>
<xsl:element name="vehicleSpeed">
<xsl:value-of select="Speed"/>
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
但是我的输出文件中没有根节点。如何做到这一点?
另外,这样改造好吗?多个模板堆叠在一起?
我建议从身份转换模板开始
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
它复制您不想转换的节点,例如 File
元素,然后允许您添加模板来执行转换,例如
<xsl:template match="Customer">
<Purchaser>
<xsl:apply-templates/>
</Purchaser>
</xsl:template>
<xsl:template match="LastName">
<Name>
<xsl:apply-templates/>
</Name>
</xsl:template>
<xsl:template match="Cars">
<vehicles>
<xsl:apply-templates/>
</vehicles>
</xsl:template>
<xsl:template match="Car">
<vehicle>
<xsl:apply-templates/>
</vehicle>
</xsl:template>
<xsl:template match="Car/*">
<xsl:element name="vehicle{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
等等。如您所见,我在大多数地方都简单地使用了文字结果元素,而不是更冗长的 xsl:element
,因为只有当您需要在 运行 时间计算名称 and/or 名称空间时才需要这样做.
Is this a good way to make the transformation? With several templates stacked?
您可以使用多个模板,也可以使用一个模板 - 在这种情况下,两种方法都没有明显的优势或劣势。就个人而言,我会保持简短并坚持使用一个模板(主要是因为您只复制一个节点而无需修改):
<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="/File">
<File>
<Purchaser>
<Name>
<xsl:value-of select="Customer/LastName"/>
</Name>
</Purchaser>
<vehicles>
<xsl:for-each select="Cars/Car">
<vehicle>
<xsl:for-each select="*">
<xsl:element name="vehicle{name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</vehicle>
</xsl:for-each>
</vehicles>
</File>
</xsl:template>
</xsl:stylesheet>