C#/.Net-解析XML/XML的快速方法->;Json

C#/.Net-解析XML/XML的快速方法->;Json,c#,xml,json,xml-parsing,xmlconvert,C#,Xml,Json,Xml Parsing,Xmlconvert,我不熟悉XML,因为现在我只使用Json:( 我有一个XML文件,如下所示: <AdapterCards> <cards type="MCS"> <card> <id>id1</id> <description>desc1</description> <mccode>code1</mccode>

我不熟悉XML,因为现在我只使用Json:( 我有一个XML文件,如下所示:

<AdapterCards>
    <cards type="MCS">
        <card>
            <id>id1</id>
            <description>desc1</description>
            <mccode>code1</mccode>
        </card>
        <card>
            <id>id2</id>
            <description>desc2</description>
            <mccode>code2</mccode>
        </card>
    </cards>
    <cards type="MCM">
        <card>
            <id>id3</id>
            <description>desc3</description>
            <mccode>code3</mccode>
        </card>
        <card>
            <id>id4</id>
            <description>desc4</description>
            <mccode>code4</mccode>
        </card>
    </cards>
    <cards type="F"/>
    <cards type="B"/>
</AdapterCards>
{[{'type': 'mcs', 'id': 'id1', 'description': 'desc1', 'mccode': 'code1'},
  {'type': 'mcs', 'id': 'id2', 'description': 'desc2', 'mccode': 'code2'},
  {'type': 'mcm', 'id': 'id3', 'description': 'desc3', 'mccode': 'code3'},
  {'type': 'mcm', 'id': 'id4', 'description': 'desc4', 'mccode': 'code4'}
]}
我的问题是,我根本没有使用过XML(是的,我感到羞耻)。 你能给我一些关于如何快速解析xml的线索吗(我把它放在一个流上,我把它上传到服务器上)。我已经搜索了一些xml到Json的转换器,但是不可能找到一个适合我需要的转换器,因为我需要一种“特殊”格式

谢谢你的回答:)!我用的是C


LINQ是提取数据的最佳方法。

使用JsonConvert类,该类包含用于此精确目的的帮助器方法:

// To convert an XML node contained in string xml into a JSON string   
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc);

// To convert JSON text contained in string json into an XML node
XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(json);

这里的文档:

我最近不得不为同一类型的东西编写一个定制的解决方案。我使用XSLT,使用
xslcomiledtransform
类运行XML输入和JSON输出

这需要一些工作,但应该有助于您的基本知识(它是从我所做的工作中复制粘贴的,已更改为几乎适合您的需要):

AdapterCards.XML

<AdapterCards>
    <cards type="MCS">
        <card>
            <id>id1</id>
            <description>desc1</description>
            <mccode>code1</mccode>
        </card>
        <card>
            <id>id2</id>
            <description>desc2</description>
            <mccode>code2</mccode>
        </card>
    </cards>
    <cards type="MCM">
        <card>
            <id>id3</id>
            <description>desc3</description>
            <mccode>code3</mccode>
        </card>
        <card>
            <id>id4</id>
            <description>desc4</description>
            <mccode>code4</mccode>
        </card>
    </cards>
    <cards type="F"/>
    <cards type="B"/>
</AdapterCards>
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="no" omit-xml-declaration="yes" method="text" encoding="UTF-8" media-type="text/x-json" />

<xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />

    <!-- Main template for escaping strings; used by above template and for object-properties 
       Responsibilities: placed quotes around string, and chain up to next filter, escape-bs-string -->
    <xsl:template name="escape-string">
        <xsl:param name="s"/>
        <xsl:text>"</xsl:text>
        <xsl:call-template name="escape-bs-string">
            <xsl:with-param name="s" select="$s"/>
        </xsl:call-template>
        <xsl:text>"</xsl:text>
    </xsl:template>

    <!-- Escape the backslash (\) before everything else. -->
    <xsl:template name="escape-bs-string">
        <xsl:param name="s"/>
        <xsl:choose>
            <xsl:when test="contains($s,'\')">
                <xsl:call-template name="escape-quot-string">
                    <xsl:with-param name="s" select="concat(substring-before($s,'\'),'\\')"/>
                </xsl:call-template>
                <xsl:call-template name="escape-bs-string">
                    <xsl:with-param name="s" select="substring-after($s,'\')"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:call-template name="escape-quot-string">
                    <xsl:with-param name="s" select="$s"/>
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <!-- Escape the double quote ("). -->
    <xsl:template name="escape-quot-string">
        <xsl:param name="s"/>
        <xsl:choose>
            <xsl:when test="contains($s,'&quot;')">
                <xsl:call-template name="encode-string">
                    <xsl:with-param name="s" select="concat(substring-before($s,'&quot;'),'\&quot;')"/>
                </xsl:call-template>
                <xsl:call-template name="escape-quot-string">
                    <xsl:with-param name="s" select="substring-after($s,'&quot;')"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:call-template name="encode-string">
                    <xsl:with-param name="s" select="$s"/>
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <!-- Replace tab, line feed and/or carriage return by its matching escape code. Can't escape backslash
       or double quote here, because they don't replace characters (&#x0; becomes \t), but they prefix 
       characters (\ becomes \\). Besides, backslash should be seperate anyway, because it should be 
       processed first. This function can't do that. -->
    <xsl:template name="encode-string">
        <xsl:param name="s"/>
        <xsl:choose>
            <!-- tab -->
            <xsl:when test="contains($s,'&#x9;')">
                <xsl:call-template name="encode-string">
                    <xsl:with-param name="s" select="concat(substring-before($s,'&#x9;'),'\t',substring-after($s,'&#x9;'))"/>
                </xsl:call-template>
            </xsl:when>
            <!-- line feed -->
            <xsl:when test="contains($s,'&#xA;')">
                <xsl:call-template name="encode-string">
                    <xsl:with-param name="s" select="concat(substring-before($s,'&#xA;'),'\n',substring-after($s,'&#xA;'))"/>
                </xsl:call-template>
            </xsl:when>
            <!-- carriage return -->
            <xsl:when test="contains($s,'&#xD;')">
                <xsl:call-template name="encode-string">
                    <xsl:with-param name="s" select="concat(substring-before($s,'&#xD;'),'\r',substring-after($s,'&#xD;'))"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$s"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>


    <xsl:template match="card">
        <xsl:text>{</xsl:text>

        <xsl:text>"type":</xsl:text>
        <xsl:call-template name="escape-string">
            <xsl:with-param name="s" select="translate(../@type, $uppercase, $smallcase)"/>
        </xsl:call-template>

        <xsl:text>,"id":</xsl:text>
        <xsl:call-template name="escape-string">
            <xsl:with-param name="s" select="id"/>
        </xsl:call-template>

        <xsl:text>,"description":</xsl:text>
        <xsl:call-template name="escape-string">
            <xsl:with-param name="s" select="description"/>
        </xsl:call-template>

        <xsl:text>,"mccode":</xsl:text>
        <xsl:call-template name="escape-string">
            <xsl:with-param name="s" select="mccode"/>
        </xsl:call-template>

        <xsl:if test="following::card">},</xsl:if>
        <xsl:if test="not(following::card)">}</xsl:if>
    </xsl:template>


    <xsl:template match="/AdapterCards">
        <xsl:text>{[</xsl:text>

        <xsl:apply-templates select="cards/card" />

        <xsl:text>]}</xsl:text>
  </xsl:template>
</xsl:stylesheet>
正如您所看到的,在需要的地方缺少逗号。但它就快到了

更新了XSL和现在在正确位置使用逗号的输出。接下来要解决的是“type”的情况。我认为您可能需要使用XSL2.0来访问
fn:lower-case()

EDIT3:完成-大小写现在转换为小写

参考资料:


你说的“快”是什么意思?执行速度?你有大量的数据吗?或者XML->C#->JSON是一个选项?你说的“特殊格式”在哪里?写得快吗?原始XML读取器(输出文本流)是我能想象到的最快的方式,但它的可重用性也较低;使用自定义JSON序列化程序将LINQ转换为XML这非常简单,但性能不好(对于大量数据)。最后,为什么不使用XSLT呢?同样,如果你没有大量的数据,这是最直接、最灵活的解决方案。@Adriano。xml没有那么大,最多400或500行。我知道,我的问题是序列化程序,但是为了能够序列化,我必须知道如何解析XML。我想使用LINQ-to-XML,因为我已经使用过LINQ-to-SQL,但我还不知道该使用哪种方法以及如何使用(如果我读了一些关于它的文章,我自己做,但我需要更快,这就是为什么我需要一些线索)。是的,XML到Json是我唯一的选择,因为客户端和服务器之间的通信只基于Json。我提到的“特殊格式”是Json字符串的结构。Thanq you:)虽然效率不高,但文件非常小:看看XSD()。它将生成C#类来读取您提供的XML文件。然后只需编写自己的JSON序列化程序(或使用内置的JSON序列化程序),我已经尝试过了,但我似乎没有Jayrock.JSON.Conversion中的SerializeXmlNode方法;jayrock.json.conversion库不是用于转换的,在这里使用这个库还有一个示例,您可以从中下载它
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="no" omit-xml-declaration="yes" method="text" encoding="UTF-8" media-type="text/x-json" />

<xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />

    <!-- Main template for escaping strings; used by above template and for object-properties 
       Responsibilities: placed quotes around string, and chain up to next filter, escape-bs-string -->
    <xsl:template name="escape-string">
        <xsl:param name="s"/>
        <xsl:text>"</xsl:text>
        <xsl:call-template name="escape-bs-string">
            <xsl:with-param name="s" select="$s"/>
        </xsl:call-template>
        <xsl:text>"</xsl:text>
    </xsl:template>

    <!-- Escape the backslash (\) before everything else. -->
    <xsl:template name="escape-bs-string">
        <xsl:param name="s"/>
        <xsl:choose>
            <xsl:when test="contains($s,'\')">
                <xsl:call-template name="escape-quot-string">
                    <xsl:with-param name="s" select="concat(substring-before($s,'\'),'\\')"/>
                </xsl:call-template>
                <xsl:call-template name="escape-bs-string">
                    <xsl:with-param name="s" select="substring-after($s,'\')"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:call-template name="escape-quot-string">
                    <xsl:with-param name="s" select="$s"/>
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <!-- Escape the double quote ("). -->
    <xsl:template name="escape-quot-string">
        <xsl:param name="s"/>
        <xsl:choose>
            <xsl:when test="contains($s,'&quot;')">
                <xsl:call-template name="encode-string">
                    <xsl:with-param name="s" select="concat(substring-before($s,'&quot;'),'\&quot;')"/>
                </xsl:call-template>
                <xsl:call-template name="escape-quot-string">
                    <xsl:with-param name="s" select="substring-after($s,'&quot;')"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:call-template name="encode-string">
                    <xsl:with-param name="s" select="$s"/>
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <!-- Replace tab, line feed and/or carriage return by its matching escape code. Can't escape backslash
       or double quote here, because they don't replace characters (&#x0; becomes \t), but they prefix 
       characters (\ becomes \\). Besides, backslash should be seperate anyway, because it should be 
       processed first. This function can't do that. -->
    <xsl:template name="encode-string">
        <xsl:param name="s"/>
        <xsl:choose>
            <!-- tab -->
            <xsl:when test="contains($s,'&#x9;')">
                <xsl:call-template name="encode-string">
                    <xsl:with-param name="s" select="concat(substring-before($s,'&#x9;'),'\t',substring-after($s,'&#x9;'))"/>
                </xsl:call-template>
            </xsl:when>
            <!-- line feed -->
            <xsl:when test="contains($s,'&#xA;')">
                <xsl:call-template name="encode-string">
                    <xsl:with-param name="s" select="concat(substring-before($s,'&#xA;'),'\n',substring-after($s,'&#xA;'))"/>
                </xsl:call-template>
            </xsl:when>
            <!-- carriage return -->
            <xsl:when test="contains($s,'&#xD;')">
                <xsl:call-template name="encode-string">
                    <xsl:with-param name="s" select="concat(substring-before($s,'&#xD;'),'\r',substring-after($s,'&#xD;'))"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$s"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>


    <xsl:template match="card">
        <xsl:text>{</xsl:text>

        <xsl:text>"type":</xsl:text>
        <xsl:call-template name="escape-string">
            <xsl:with-param name="s" select="translate(../@type, $uppercase, $smallcase)"/>
        </xsl:call-template>

        <xsl:text>,"id":</xsl:text>
        <xsl:call-template name="escape-string">
            <xsl:with-param name="s" select="id"/>
        </xsl:call-template>

        <xsl:text>,"description":</xsl:text>
        <xsl:call-template name="escape-string">
            <xsl:with-param name="s" select="description"/>
        </xsl:call-template>

        <xsl:text>,"mccode":</xsl:text>
        <xsl:call-template name="escape-string">
            <xsl:with-param name="s" select="mccode"/>
        </xsl:call-template>

        <xsl:if test="following::card">},</xsl:if>
        <xsl:if test="not(following::card)">}</xsl:if>
    </xsl:template>


    <xsl:template match="/AdapterCards">
        <xsl:text>{[</xsl:text>

        <xsl:apply-templates select="cards/card" />

        <xsl:text>]}</xsl:text>
  </xsl:template>
</xsl:stylesheet>
// Load XML document
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("AdapterCards.XML");

// Transform the XML into JSON
XslCompiledTransform transformer = new XslCompiledTransform();
using (var xslStylesheetFile = File.Open("AdapterCards.XSL", FileMode.Open))
{
    using (var xmlReader = new XmlTextReader(xslStylesheetFile))
    {
        transformer.Load(xmlReader);
    }
}
var sourceNavigator = xmlDoc.CreateNavigator();
using (MemoryStream ms = new MemoryStream())
{
    transformer.Transform(sourceNavigator, null, ms);
    ms.Position = 0;
    using (var sr = new StreamReader(ms))
    {
        return sr.ReadToEnd(); // <-- this is your JSON
    }
}
{[{"type":"mcs","id":"id1","description":"desc1","mccode":"code1"},
{"type":"mcs","id":"id2","description":"desc2","mccode":"code2"},
{"type":"mcm","id":"id3","description":"desc3","mccode":"code3"},
{"type":"mcm","id":"id4","description":"desc4","mccode":"code4"}]}