C# XSL在XML转换中创建子元素失败

C# XSL在XML转换中创建子元素失败,c#,xml,xslt,C#,Xml,Xslt,试着,试着让下面的工作。我有一个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>1

试着,试着让下面的工作。我有一个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>
使行成为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>

很明显,我遗漏了一些东西,但经过几个小时的尝试,我无法让输出行元素成为有序的子元素。有人能给我指出正确的方向吗?还有,为什么缩进选项似乎只影响输出xml的第一级?

您有一个模板匹配的标题,但在这个标题中,您可以获取行元素,但行不是标题的子元素,所以这不会选择任何内容

由于XSLT的原因,输出中的行元素实际上是被选中的。您没有模板匹配顺序,因此使用XSLT的内置模板,该模板将选择顺序下的标题和行元素

一种解决方案是将模板匹配标题改为匹配顺序

试试这个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>
请注意,使用可简化订单上数字属性的创建。

另一种解决方案是在../Line上使用xsl:apply templates,而不是在模板上使用mode属性的Line。因此,对模板的更改是最小的

<?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>

回答得很好,谢谢你让我看到了整个周末我都在面对的错误。现在让我的转换工作。