使用XSLT修改XML文件

Posted on 2010-07-28 13:39  sky-v  阅读(2028)  评论(0编辑  收藏  举报

近来在做项目时需要将XML格式进行转换,于是便使用了XSLT来进行格式转换工作。

 

XSLT介绍

    XSLT是一种将XML文档转换为其他文本文档的语言,是建立在XMLXPath之上的国际标准,内容比较多,功能强大。

    对于编程人员来说,XSLT可以看作以前序遍历的方式专门处理XML树状结构的标记语言。以前编程根据XML文档输出纯文本数据时需要写代码以前序遍历方式的方式遍历XML文档对象组成的树状结构,对于每一个特定名称或特定层次的XML节点而输出不同的内容,这个过程比较复杂,代码量大,需用进行很多的状态判断。而XSLT则使用一种简洁明了的标记语言实现了相同的逻辑。因此XSLT从程序逻辑的角度看类似支持递归的编程语言,而且是专门处理XML文档的。

    XSLT转换过程会涉及到三个文本文档,一个是要处理的原始XML文档,第二个就是XSLT样式表文档,该文档包含了XSLT代码,XSLT代码本身就是XML格式,但使用了XML的名称空间。第三个就是XSLT处理输出的文本文档,注意,此处输出的是纯文本文档,这个文档具体是什么格式完全靠XSLT代码来决定,可以是另外一个XML文档,HTML文档,SQL语句字符串或者其他任意格式的字符串数据等等,XSLT转换只能输出纯文本文档,此外就没有限制输出文档的具体格式。

    数据XML文档是一个很简单的XML文档,此处不加说明了。重点说说XSLT样式表文档,XSLT样式表文档本身是一个XML文档。它采用XML的树状结构来描述递归处理过程,也比较好理解。

    在样式表文档中,根元素为 xsl:stylesheet ,里面定义了一个名为xsl的名称空间,这个根节点及其属性值都是固定的。

xsl:output 元素是可选的,它的method属性用于指定输出文档的格式,可以设置为xmlhtmltext值。此处使用xml输出样式,说明输出的文档是XML格式的,XSLT转换会尽量生成XML文档,但不作保证,因此仍然有可能生成不合格的XML文档。

    xsl:template 用于定义一个XSLT模板,模板类似编程语言中的函数,可实现XSLT代码的重用。模板可以使用name属性定义名称,也可以使用match属性定义匹配的XPath路径,这个模板使用了match属性来匹配XML文档本身。

    然后是 html 元素,由于html元素没有使用xsl的前缀,因此不属于xslt代码,因此将原样输出,跟着后面的bodytable元素也是一样的。

    xsl:for-each 元素类似C#中的foreach 语法结果,表示循环遍历元素,它使用select属性指定一个XPath相对路径,XSLT使用这个相对路径查询所有要遍历的XML节点,此时当前节点就是XML文档本身,因此XSLT处理器会调用XmlDocumentSelectNodes 函数来获得要遍历的XML节点,函数的参数就是Table/Record。于是我们开始循环遍历所有的Record元素了。

    在循环遍历Record元素时,对每一个Record元素都要输出xsl:for-each的子节点,首先是 tr 元素,这不是XSLT元素,因此原样输出。这里还套嵌定义了另外一个for-each元素,于是我们又开始了一个新的循环遍历了,新的循环指定的相对XPath路径是一个星号,表示匹配所有名称的子元素,这类似DOS命令Dir中使用星号匹配所有文件。此处表示循环遍历Record元素下面所有的字段元素。

    对每一个字段元素,首先输出td 元素,然后处理xsl:value-of 元素,xsl:value-of 表示输出指定相对路径的节点的值,这里指定的XPath是一个点号,表示当前节点本身,由于当前节点是XML元素,因此也就输出元素的文本内容,相当于输出XmlElementInnerText 属性值。

xslt文件:

<?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" encoding="utf-8"/>

 <xsl:template match="/">
  <xsl:for-each select="Category">
   <Category>
    <xsl:attribute name="Navigate">
     <xsl:value-of select="@Navigate"/>
    </xsl:attribute>
    <xsl:element name="Name">
     <xsl:value-of select="Name"/>
    </xsl:element>
    <xsl:element name="EngName">
     <xsl:value-of select="EngName"/>
    </xsl:element>
    <xsl:element name="ChtName">
     <xsl:value-of select="ChtName"/>
    </xsl:element>
    <xsl:element name="Description">
     <xsl:value-of select="Description"/>
    </xsl:element>
    <xsl:element name="EngDescription">
     <xsl:value-of select="EngDescription"/>
    </xsl:element>
    <xsl:element name="ChtDescription">
     <xsl:value-of select="ChtDescription"/>
    </xsl:element>
    <xsl:element name="Editor">
     <xsl:value-of select="Editor"/>
    </xsl:element>
    <xsl:element name="LastModified">
     <xsl:value-of select="LastModified"/>
    </xsl:element>
    <xsl:element name="Identity">
     <xsl:text>CAT_ZTF</xsl:text>
    </xsl:element>
    <xsl:element name="Notes">
     <xsl:value-of select="Notes"/>
    </xsl:element>
    <xsl:element name="TotalCount">
     <xsl:text>{0}</xsl:text>
    </xsl:element>
    <xsl:for-each select="Content">
     <xsl:for-each select="CatItem">
      <xsl:element name="CatItem">
       <xsl:attribute name="Name">
        <xsl:value-of select="@Name"/>
       </xsl:attribute>
       <xsl:attribute name="Code">
        <xsl:value-of select="@Code"/>
       </xsl:attribute>
       <xsl:attribute name="ParentCode">
        <xsl:value-of select="@ParentCode"/>
       </xsl:attribute>
       <xsl:attribute name="CategoryType">
        <xsl:text>CAT_ZTF</xsl:text>
       </xsl:attribute>
      </xsl:element>
     </xsl:for-each>
    </xsl:for-each>
   </Category>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>


原XML文件:

<?xml version="1.0" encoding="GB2312"?>
<Category Navigate="1">
 <Name>专用分类</Name>
 <EngName>New</EngName>
 <ChtName>專用分類</ChtName>
 <Description/>
 <EngDescription/>
 <ChtDescription/>
 <Editor>Liangying</Editor>
 <LastModified>2010-5-31</LastModified>
 <Identity>CAT_XXXX</Identity>
 <Notes>专用分类</Notes>
 <Content Count="97">

<CatItem Name="文艺" Description="" EngDescription="" ChtDescription="" Code="001" ParentCode="" Nav="tttt?={0}"/>
  <CatItem Name="小说" Description="" EngDescription="" ChtDescription="" Code="001001" ParentCode="001" Nav="tttt?={0}"/>
  <CatItem Name="文学" Description="" EngDescription="" ChtDescription="" Code="001002" ParentCode="001" Nav="tttt?={0}"/>
  <CatItem Name="散文" Description="" EngDescription="" ChtDescription="" Code="001003" ParentCode="001" Nav="tttt?={0}"/>

</Content>
</Category>

 

转换C#代码:

 

/// </summary>
        /// <param name="strXmlPath"></param>
        /// <param name="strXsltPath"></param>
        /// <returns></returns>
        public string TransferXmlByXSLT(string strXmlPath,string strXsltPath)
        {

            MemoryStream fs = new MemoryStream();
            string outputstring = string.Empty;
            try
            {
                //判断文件是否存在
                if (File.Exists(Server.MapPath(strXmlPath)) && File.Exists(Server.MapPath(strXsltPath)))
                {
                    //加载xml文件
                    XPathDocument doc = new XPathDocument(strXmlPath);
                    XslTransform transForm = new XslTransform();
                    //加载xslt文件
                    transForm.Load(strXsltPath);
                    XPathNavigator nav = doc.CreateNavigator();
                    //转换xml
                    transForm.Transform(nav, null, fs);
                    fs.Seek(0, SeekOrigin.Begin);
                    StreamReader stream = new StreamReader(fs);
                    outputstring = stream.ReadToEnd();

                    fs.Close();
                    fs.Dispose();
                }
                else
                {
                    return "";
                }
            }
            finally
            {
                fs.Close();
                fs.Dispose();
            }

            return outputstring;
        }

 

转换后的XML:

<?xml version="1.0" encoding="GB2312"?>
<Category Navigate="1">
 <Name>专用分类</Name>
 <EngName>New</EngName>
 <ChtName>專用分類</ChtName>
 <Description/>
 <EngDescription/>
 <ChtDescription/>
 <Editor>Liangying</Editor>
 <LastModified>2010-5-31</LastModified>
 <Identity>CAT_XXXX</Identity>
 <Notes>专用分类</Notes>
 <TotalCount>{0}</TotalCount>

<CatItem Name="文艺" Code="001" CategoryType="CAT_ZTF" ParentCode=""  />
  <CatItem Name="小说" Code="001001" CategoryType="CAT_ZTF" ParentCode="001"  />
  <CatItem Name="文学" Code="001002" CategoryType="CAT_ZTF" ParentCode="001"  />

<CatItem Name="散文" Code="001003" CategoryType="CAT_ZTF" ParentCode="001"  />

</Category>

Copyright © 2024 sky-v
Powered by .NET 9.0 on Kubernetes