使用XSLT将XML值拆分为新的XML

本文关键字:XML 拆分 XSLT 使用 | 更新日期: 2023-09-27 17:59:42

是否可以使用XSLT或C#从

<XML>
  <Name>Name1;Name2</Name> 
  <Adress>Adress1;Adress2</Adress>
</XML>

到此

<XML>
    <LINE>
        <Name>Name1</Name> 
        <Adress>Adress1</Adress> 
    </LINE>
    <LINE>
        <Name>Name2</Name> 
        <Adress>Adress2</Adress> 
   </LINE>
</XML>

任何帮助都将不胜感激。

使用XSLT将XML值拆分为新的XML

此XSLT2.0转换:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:template match="/*">
  <xsl:copy>
    <xsl:variable name="vTop" select="."/>
    <xsl:variable name="vAddresses" select="tokenize(Adress, ';')"/>
    <xsl:for-each select="tokenize(Name, ';')">
     <xsl:variable name="vPos" select="position()" as="xs:integer"/>
     <xsl:apply-templates select="$vTop/Name">
       <xsl:with-param name="pNameData" select="."/>
       <xsl:with-param name="pAdrData" select="$vAddresses[$vPos]"/>
     </xsl:apply-templates>
    </xsl:for-each>
  </xsl:copy>
 </xsl:template>
 <xsl:template match="Name">
  <xsl:param name="pNameData"/>
  <xsl:param name="pAdrData"/>
  <Line>
   <Name><xsl:value-of select="$pNameData"/></Name>
   <Adress><xsl:value-of select="$pAdrData"/></Adress>
  </Line>
 </xsl:template>
</xsl:stylesheet>

应用于所提供的XML文档时:

<XML>
    <Name>Name1;Name2</Name>
    <Adress>Adress1;Adress2</Adress>
</XML>

生成所需的正确结果:

<XML>
   <Line>
      <Name>Name1</Name>
      <Adress>Adress1</Adress>
   </Line>
   <Line>
      <Name>Name2</Name>
      <Adress>Adress2</Adress>
   </Line>
</XML>

这里有一个非常简单的XSLT1.0解决方案:

输入文件

<XML>
  <Name>Name1;Name2</Name> 
  <Address>Address1;Address2</Address>
  <Name>Name3;Name4</Name> 
  <Address>Address3;Address4</Address>
</XML>

样式表

<?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" indent="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:template match="XML">
    <XML>
      <xsl:apply-templates select="Name"/>
    </XML>
  </xsl:template>
  <xsl:template match="Name" mode="name-address">
    <xsl:param name="name" select="substring-before(., ';')"/>
    <xsl:param name="address" select="substring-before(following-sibling::*[1][self::Address], ';')"/>
    <LINE>
      <Name>
        <xsl:value-of select="$name"/>
      </Name>
      <Address>
        <xsl:value-of select="$address"/>
      </Address>
    </LINE>
  </xsl:template>
  <xsl:template match="Name">
    <xsl:apply-templates select="." mode="name-address"/>
    <xsl:apply-templates select="." mode="name-address">
      <xsl:with-param name="name" select="substring-after(., ';')"/>
      <xsl:with-param name="address" select="substring-after(following-sibling::*[1][self::Address], ';')"/>
    </xsl:apply-templates>
  </xsl:template>
</xsl:stylesheet>

输出

<?xml version="1.0" encoding="UTF-8"?>
<XML>
   <LINE>
      <Name>Name1</Name>
      <Address>Address1</Address>
   </LINE>
   <LINE>
      <Name>Name2</Name>
      <Address>Address2</Address>
   </LINE>
   <LINE>
      <Name>Name3</Name>
      <Address>Address3</Address>
   </LINE>
   <LINE>
      <Name>Name4</Name>
      <Address>Address4</Address>
   </LINE>
</XML>

我不知道XSLT,但如果可能的话,可能会有一个非常复杂的解决方案。

不过,在C#中,它相当简单。这里有一种方法(使用LINQ到XML):

var inputXml = 
    @"<XML>
        <Name>Name1;Name2</Name> 
        <Adress>Adress1;Adress2</Adress>
    </XML>";
var inputXmlDoc = XDocument.Parse(inputXml);
var names = inputXmlDoc.Root.Descendants("Name").Single().Value.Split(';');
var addresses = inputXmlDoc.Root.Descendants("Adress").Single().Value.Split(';');
var outputXmlDoc = new XDocument(
    new XElement("XML",
        names.Zip(addresses, (n, a) => new {n, a})
            .Select(pair => new XElement("LINE",
                    new XElement("Name", pair.n),
                    new XElement("Address", pair.a)
            ))
        )
    );
Console.WriteLine(outputXmlDoc);