尝试并尝试让以下内容正常运行。我有一个类似于
的XML文件(序列化的C#类)<?xml version="1.0" encoding="utf-8"?>
<MyXml xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Order>
<Header>
<OrderNumber>1234</OrderNumber>
</Header>
<Line>
<Sku>abc</Sku>
<Qty>300</Qty>
</Line>
<Line>
<Sku>xyz</Sku>
<Qty>19</Qty>
</Line>
</Order>
我需要将其转换为:
<?xml version="1.0" encoding="utf-8"?>
<Order Number="1234">
<Line>
<Product>abc</Product>
<Quantity>300</Quantity>
</Line>
<Line>
<Product>xyz</Product>
<Quantity>19</Quantity>
</Line>
</Order>
使行元素的子行为。
到目前为止,这是我最成功的尝试。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Header" >
<Order>
<xsl:attribute name="Number">
<xsl:value-of select="OrderNumber"/>
</xsl:attribute>
<xsl:apply-templates select="Line"/>
</Order>
</xsl:template>
<xsl:template match="Line">
<Line>
<Product>
<xsl:value-of select="Sku" />
</Product>
<Quantity>
<xsl:value-of select="Qty" />
</Quantity>
</Line>
</xsl:template>
</xsl:stylesheet>
使用多个根节点生成下面不正确的xml。
<?xml version="1.0" encoding="utf-8"?>
<Order OrderNumber="1234" />
<Line><Product>abc</Product><Quantity>300</Quantity></Line>
<Line><Product>xyz</Product><Quantity>19</Quantity></Line>
显然我缺少一些东西,但经过几个小时的尝试后,我无法将输出的Line元素视为Order的子元素。有人能指出我正确的方向吗?另外为什么缩进选项似乎只影响输出xml的第一级?
答案 0 :(得分:1)
您有一个匹配Header
的模板,但是在<xsl:apply-templates select="Line"/>
之内您需要Line
来获取Line
元素,但Header
不是Line
的孩子,所以这什么都不选。
由于XSLT built-in template rules,实际上正在选择输出中的Order
元素。您没有匹配Header
的模板,因此使用了XSLT的内置模板,该模板将选择{{1}下的Line
和Order
元素}}
一种解决方案是将匹配Header
的模板更改为匹配Order
。
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Order" >
<Order Number="{Header/OrderNumber}">
<xsl:apply-templates select="Line"/>
</Order>
</xsl:template>
<xsl:template match="Line">
<Line>
<Product>
<xsl:value-of select="Sku" />
</Product>
<Quantity>
<xsl:value-of select="Qty" />
</Quantity>
</Line>
</xsl:template>
</xsl:stylesheet>
请注意使用Attribute Value Templates来简化Number
上Order
属性的创建。
答案 1 :(得分:0)
另一种解决方案是在xsl:apply-templates
上使用../Line
而不是Line
,并在模板上使用mode
属性。因此,对模板的更改很少。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Header" >
<Order>
<xsl:attribute name="Number">
<xsl:value-of select="OrderNumber"/>
</xsl:attribute>
<xsl:apply-templates select="../Line" mode="sub"/> <!-- set 'mode' to 'sub' and add '../' to XPath-->
</Order>
</xsl:template>
<xsl:template match="Line" mode="sub"> <!-- use template only when 'mode' is set to 'sub' -->
<Line>
<Product>
<xsl:value-of select="Sku" />
</Product>
<Quantity>
<xsl:value-of select="Qty" />
</Quantity>
</Line>
</xsl:template>
<xsl:template match="text()" /> <!-- ignore all unmatched text() nodes -->
</xsl:stylesheet>