C# 如何从另一个xml元数据创建xml?

C# 如何从另一个xml元数据创建xml?,c#,.net,xml,xslt,C#,.net,Xml,Xslt,我不确定这个标题是否清楚地解释了我的问题,我会尽可能多地介绍细节 我需要使用XSLT1将下面的xml转换为格式正确的xml,以便将其反序列化为.net类型 源XML <ax21:result type="test.ws.Result"> <ax21:columnNames>fileName</ax21:columnNames> <ax21:columnNames>

我不确定这个标题是否清楚地解释了我的问题,我会尽可能多地介绍细节

我需要使用XSLT1将下面的xml转换为格式正确的xml,以便将其反序列化为.net类型

源XML

            <ax21:result type="test.ws.Result">
                <ax21:columnNames>fileName</ax21:columnNames>
                <ax21:columnNames>lockedState</ax21:columnNames>
                <ax21:columnNames>currentLockOwner</ax21:columnNames>
                <ax21:columnNames>UUID</ax21:columnNames>
                <ax21:resultData>Test1.doc</ax21:resultData>
                <ax21:resultData>true</ax21:resultData>
                <ax21:resultData>analyst</ax21:resultData>
                <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
                <ax21:resultData>Test2.doc</ax21:resultData>
                <ax21:resultData>false</ax21:resultData>
                <ax21:resultData/>
                <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
                <ax21:resultData>Test3.doc</ax21:resultData>
                <ax21:resultData>true</ax21:resultData>
                <ax21:resultData>analyst</ax21:resultData>
                <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
                <ax21:resultData>Test4.doc</ax21:resultData>
                <ax21:resultData>false</ax21:resultData>
                <ax21:resultData/>
                <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
            </ax21:result>

文件名
锁定状态
当前锁所有者
UUID
Test1.doc
真的
分析师
f48f0450-9ecc-4a44-b063-898d9d72d112
Test2.doc
假的
f48f0450-9ecc-4a44-b063-898d9d72d112
Test3.doc
真的
分析师
f48f0450-9ecc-4a44-b063-898d9d72d112
Test4.doc
假的
f48f0450-9ecc-4a44-b063-898d9d72d112
目标XML

<result>
    <item>
        <fileName>Test1.doc</fileName>
        <lockedState>true</lockedState>
        <currentLockOwner>analyst</currentLockOwner>
        <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
    </item>
    <item>
        <fileName>Test2.doc</fileName>
        <lockedState>true</lockedState>
        <currentLockOwner>analyst</currentLockOwner>
        <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
    </item>
    <item>
        <fileName>Test2.doc</fileName>
        <lockedState>true</lockedState>
        <currentLockOwner>analyst</currentLockOwner>
        <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
    </item>
</result>

Test1.doc
真的
分析师
f48f0450-9ecc-4a44-b063-898d9d72d112
Test2.doc
真的
分析师
f48f0450-9ecc-4a44-b063-898d9d72d112
Test2.doc
真的
分析师
f48f0450-9ecc-4a44-b063-898d9d72d112
这可以使用xslt实现吗?如果是,请发布链接或示例xslt供我尝试


我正在使用.NET2.0、c#、XSLT1.0,要正确可靠地完成这项工作,即使不是不可能,也是非常困难的

问题是:在多个节点上没有索引或类型的指示,它们的类型/位置是什么-你必须或多或少地猜测

这将是一个不同的故事,如果至少有一个额外的属性,诸如此类的东西-这样一个人可以以某种方式将它们联系在一起

你有没有可能稍微“按摩”一下原始数据??否则,我可能会说,您必须在C#中加载它并对其进行解析,然后进行大量手动处理,以获得所需的内容


Marc

这是一个相当简单的解决方案

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ax21="my:ax21" exclude-result-prefixes="ax21"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:variable name="vCols" select="/*/ax21:columnNames"/>
  <xsl:variable name="vNumCols" select="count($vCols)"/>

    <xsl:template match="ax21:result">
        <result>
          <xsl:apply-templates select=
           "ax21:resultData[position() mod $vNumCols = 1]"
           />
        </result>
    </xsl:template>

    <xsl:template match="ax21:resultData">
      <item>
        <xsl:apply-templates mode="create" select=
         "(.|following-sibling::ax21:resultData)
                               [not(position() > $vNumCols) ]
         "/>
      </item>
    </xsl:template>

    <xsl:template match="ax21:resultData" mode="create">
      <xsl:variable name="vPos" select="position()"/>
    <xsl:element name="{$vCols[$vPos]}">
          <xsl:value-of select="."/>
          <xsl:if test="not(text())">
            <xsl:value-of select=
             "(.| preceding-sibling::ax21:resultData)
                         [position() mod $vNumCols = $vPos]
                            [text()]
                                  [last()]
             "/>
          </xsl:if>
    </xsl:element>
    </xsl:template>
</xsl:stylesheet>
<ax21:result type="test.ws.Result"
 xmlns:ax21="my:ax21"
>
    <ax21:columnNames>fileName</ax21:columnNames>
    <ax21:columnNames>lockedState</ax21:columnNames>
    <ax21:columnNames>currentLockOwner</ax21:columnNames>
    <ax21:columnNames>UUID</ax21:columnNames>
    <ax21:resultData>Test1.doc</ax21:resultData>
    <ax21:resultData>true</ax21:resultData>
    <ax21:resultData>analyst</ax21:resultData>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test2.doc</ax21:resultData>
    <ax21:resultData>false</ax21:resultData>
    <ax21:resultData/>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test3.doc</ax21:resultData>
    <ax21:resultData>true</ax21:resultData>
    <ax21:resultData>analyst</ax21:resultData>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test4.doc</ax21:resultData>
    <ax21:resultData>false</ax21:resultData>
    <ax21:resultData/>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
</ax21:result>
<result>
   <item>
      <fileName>Test1.doc</fileName>
      <lockedState>true</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test2.doc</fileName>
      <lockedState>false</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test3.doc</fileName>
      <lockedState>true</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test4.doc</fileName>
      <lockedState>false</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
</result>

当此转换应用于以下XML文档时

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ax21="my:ax21" exclude-result-prefixes="ax21"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:variable name="vCols" select="/*/ax21:columnNames"/>
  <xsl:variable name="vNumCols" select="count($vCols)"/>

    <xsl:template match="ax21:result">
        <result>
          <xsl:apply-templates select=
           "ax21:resultData[position() mod $vNumCols = 1]"
           />
        </result>
    </xsl:template>

    <xsl:template match="ax21:resultData">
      <item>
        <xsl:apply-templates mode="create" select=
         "(.|following-sibling::ax21:resultData)
                               [not(position() > $vNumCols) ]
         "/>
      </item>
    </xsl:template>

    <xsl:template match="ax21:resultData" mode="create">
      <xsl:variable name="vPos" select="position()"/>
    <xsl:element name="{$vCols[$vPos]}">
          <xsl:value-of select="."/>
          <xsl:if test="not(text())">
            <xsl:value-of select=
             "(.| preceding-sibling::ax21:resultData)
                         [position() mod $vNumCols = $vPos]
                            [text()]
                                  [last()]
             "/>
          </xsl:if>
    </xsl:element>
    </xsl:template>
</xsl:stylesheet>
<ax21:result type="test.ws.Result"
 xmlns:ax21="my:ax21"
>
    <ax21:columnNames>fileName</ax21:columnNames>
    <ax21:columnNames>lockedState</ax21:columnNames>
    <ax21:columnNames>currentLockOwner</ax21:columnNames>
    <ax21:columnNames>UUID</ax21:columnNames>
    <ax21:resultData>Test1.doc</ax21:resultData>
    <ax21:resultData>true</ax21:resultData>
    <ax21:resultData>analyst</ax21:resultData>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test2.doc</ax21:resultData>
    <ax21:resultData>false</ax21:resultData>
    <ax21:resultData/>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test3.doc</ax21:resultData>
    <ax21:resultData>true</ax21:resultData>
    <ax21:resultData>analyst</ax21:resultData>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test4.doc</ax21:resultData>
    <ax21:resultData>false</ax21:resultData>
    <ax21:resultData/>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
</ax21:result>
<result>
   <item>
      <fileName>Test1.doc</fileName>
      <lockedState>true</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test2.doc</fileName>
      <lockedState>false</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test3.doc</fileName>
      <lockedState>true</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test4.doc</fileName>
      <lockedState>false</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
</result>

文件名
锁定状态
当前锁所有者
UUID
Test1.doc
真的
分析师
f48f0450-9ecc-4a44-b063-898d9d72d112
Test2.doc
假的
f48f0450-9ecc-4a44-b063-898d9d72d112
Test3.doc
真的
分析师
f48f0450-9ecc-4a44-b063-898d9d72d112
Test4.doc
假的
f48f0450-9ecc-4a44-b063-898d9d72d112
产生所需结果

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ax21="my:ax21" exclude-result-prefixes="ax21"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:variable name="vCols" select="/*/ax21:columnNames"/>
  <xsl:variable name="vNumCols" select="count($vCols)"/>

    <xsl:template match="ax21:result">
        <result>
          <xsl:apply-templates select=
           "ax21:resultData[position() mod $vNumCols = 1]"
           />
        </result>
    </xsl:template>

    <xsl:template match="ax21:resultData">
      <item>
        <xsl:apply-templates mode="create" select=
         "(.|following-sibling::ax21:resultData)
                               [not(position() > $vNumCols) ]
         "/>
      </item>
    </xsl:template>

    <xsl:template match="ax21:resultData" mode="create">
      <xsl:variable name="vPos" select="position()"/>
    <xsl:element name="{$vCols[$vPos]}">
          <xsl:value-of select="."/>
          <xsl:if test="not(text())">
            <xsl:value-of select=
             "(.| preceding-sibling::ax21:resultData)
                         [position() mod $vNumCols = $vPos]
                            [text()]
                                  [last()]
             "/>
          </xsl:if>
    </xsl:element>
    </xsl:template>
</xsl:stylesheet>
<ax21:result type="test.ws.Result"
 xmlns:ax21="my:ax21"
>
    <ax21:columnNames>fileName</ax21:columnNames>
    <ax21:columnNames>lockedState</ax21:columnNames>
    <ax21:columnNames>currentLockOwner</ax21:columnNames>
    <ax21:columnNames>UUID</ax21:columnNames>
    <ax21:resultData>Test1.doc</ax21:resultData>
    <ax21:resultData>true</ax21:resultData>
    <ax21:resultData>analyst</ax21:resultData>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test2.doc</ax21:resultData>
    <ax21:resultData>false</ax21:resultData>
    <ax21:resultData/>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test3.doc</ax21:resultData>
    <ax21:resultData>true</ax21:resultData>
    <ax21:resultData>analyst</ax21:resultData>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test4.doc</ax21:resultData>
    <ax21:resultData>false</ax21:resultData>
    <ax21:resultData/>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
</ax21:result>
<result>
   <item>
      <fileName>Test1.doc</fileName>
      <lockedState>true</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test2.doc</fileName>
      <lockedState>false</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test3.doc</fileName>
      <lockedState>true</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test4.doc</fileName>
      <lockedState>false</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
</result>

Test1.doc
真的
分析师
f48f0450-9ecc-4a44-b063-898d9d72d112
Test2.doc
假的
分析师
f48f0450-9ecc-4a44-b063-898d9d72d112
Test3.doc
真的
分析师
f48f0450-9ecc-4a44-b063-898d9d72d112
Test4.doc
假的
分析师
f48f0450-9ecc-4a44-b063-898d9d72d112
说明

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ax21="my:ax21" exclude-result-prefixes="ax21"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:variable name="vCols" select="/*/ax21:columnNames"/>
  <xsl:variable name="vNumCols" select="count($vCols)"/>

    <xsl:template match="ax21:result">
        <result>
          <xsl:apply-templates select=
           "ax21:resultData[position() mod $vNumCols = 1]"
           />
        </result>
    </xsl:template>

    <xsl:template match="ax21:resultData">
      <item>
        <xsl:apply-templates mode="create" select=
         "(.|following-sibling::ax21:resultData)
                               [not(position() > $vNumCols) ]
         "/>
      </item>
    </xsl:template>

    <xsl:template match="ax21:resultData" mode="create">
      <xsl:variable name="vPos" select="position()"/>
    <xsl:element name="{$vCols[$vPos]}">
          <xsl:value-of select="."/>
          <xsl:if test="not(text())">
            <xsl:value-of select=
             "(.| preceding-sibling::ax21:resultData)
                         [position() mod $vNumCols = $vPos]
                            [text()]
                                  [last()]
             "/>
          </xsl:if>
    </xsl:element>
    </xsl:template>
</xsl:stylesheet>
<ax21:result type="test.ws.Result"
 xmlns:ax21="my:ax21"
>
    <ax21:columnNames>fileName</ax21:columnNames>
    <ax21:columnNames>lockedState</ax21:columnNames>
    <ax21:columnNames>currentLockOwner</ax21:columnNames>
    <ax21:columnNames>UUID</ax21:columnNames>
    <ax21:resultData>Test1.doc</ax21:resultData>
    <ax21:resultData>true</ax21:resultData>
    <ax21:resultData>analyst</ax21:resultData>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test2.doc</ax21:resultData>
    <ax21:resultData>false</ax21:resultData>
    <ax21:resultData/>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test3.doc</ax21:resultData>
    <ax21:resultData>true</ax21:resultData>
    <ax21:resultData>analyst</ax21:resultData>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
    <ax21:resultData>Test4.doc</ax21:resultData>
    <ax21:resultData>false</ax21:resultData>
    <ax21:resultData/>
    <ax21:resultData>f48f0450-9ecc-4a44-b063-898d9d72d112</ax21:resultData>
</ax21:result>
<result>
   <item>
      <fileName>Test1.doc</fileName>
      <lockedState>true</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test2.doc</fileName>
      <lockedState>false</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test3.doc</fileName>
      <lockedState>true</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
   <item>
      <fileName>Test4.doc</fileName>
      <lockedState>false</lockedState>
      <currentLockOwner>analyst</currentLockOwner>
      <UUID>f48f0450-9ecc-4a44-b063-898d9d72d112</UUID>
   </item>
</result>
  • 为方便起见,列名及其编号收集在全局变量
    $vCols
    $vNumCols

  • 我们将模板应用于第N个
    ax21:resultData
    元素,其中
    N mod$vNumCols=1
    。每个这样的元素都会启动一个新的

  • 每个
    ax21:resultData
    元素都将是
    项中的第一个
    元素,并在“无模式”下与模板匹配。这只需创建包装
    元素,并应用于所有当前的$vNumCols
    ax21:resultData
    元素另一个模板--在
    的“创建”
    模式下

  • “create”
    模式中的模板只创建一个元素,其名称是
    $vCols
    中第n个元素的值,其中
    n
    是模板应用到的当前()节点的
    位置()

  • 最后,如果碰巧没有提供任何值,我们将(按倒序)获得同一类型元素的最新非空值


  • 该源XML仅为XML格式。它绝对不符合XML的“精神”,因此任何使用XSL的解决方案充其量都是黑客的。如果您对源代码格式有任何控制权,我强烈建议您将其更改为层次结构。解决方案中没有“黑客”的内容。XSLT可以为许多“非传统”或看似“无法解决”的问题提供优雅的解决方案。谢谢Dimitre!!。我不确定XSLT是否可以解决这个问题,我只是把它发布在这里,以获取您对这个问题的意见。再次感谢。另一方面,自从我发布这篇文章后,xml结构发生了变化,它更加正确,并且有一个马克建议的索引。你上面的答案将帮助我创建新的模板。再次感谢。@gk不客气!:)有许多问题似乎比这更“棘手”,可以用XSLT优雅地解决。在很短的时间内,我已经解决了60个Project Euler问题,其中任何一个问题(用钢笔和铅笔都无法解决)的解决方案都是用XSLT实现的。+1-回答得很好,展示了XSLT可以做的事情-做得很好!一点也不难!当然,绝对有可能。XSLT是一种功能强大的语言,为此类问题提供了优雅的解决方案。人们只需要想一想:)我也有类似的想法,我在等待迪米特的回应。无论如何,我已经与另一个团队合作,以使xml具有更有意义的结构。伙计们,如果您想看到一些真正具有挑战性的问题的优雅XSLT解决方案,请看这里: