я должен был написать на заказ решения для того же типа вещей сам недавно. Я сделал это с помощью XSLT, используя класс XslCompiledTransform
для запуска ввода 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>
AdapterCards.XSL
<?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,'"')">
<xsl:call-template name="encode-string">
<xsl:with-param name="s" select="concat(substring-before($s,'"'),'\"')"/>
</xsl:call-template>
<xsl:call-template name="escape-quot-string">
<xsl:with-param name="s" select="substring-after($s,'"')"/>
</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 (� 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,'	')">
<xsl:call-template name="encode-string">
<xsl:with-param name="s" select="concat(substring-before($s,'	'),'\t',substring-after($s,'	'))"/>
</xsl:call-template>
</xsl:when>
<!-- line feed -->
<xsl:when test="contains($s,'
')">
<xsl:call-template name="encode-string">
<xsl:with-param name="s" select="concat(substring-before($s,'
'),'\n',substring-after($s,'
'))"/>
</xsl:call-template>
</xsl:when>
<!-- carriage return -->
<xsl:when test="contains($s,'
')">
<xsl:call-template name="encode-string">
<xsl:with-param name="s" select="concat(substring-before($s,'
'),'\r',substring-after($s,'
'))"/>
</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>
C#
// 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
}
}
Я выполнил над XSL в Notepad ++ и получил следующее:
{[{"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"}]}
Как вы можете видеть, что есть запятые отсутствуют, где они должны быть. Но это почти что!
Обновлен XSL и вывод, который теперь работает с запятыми в нужном месте. Следующее, что нужно исправить, - это случай «типа». Я думаю, вам, возможно, потребуется использовать XSL 2.0, чтобы получить доступ к xpath functionfn:lower-case()
.
EDIT3: Выполнено - дело в настоящее время переведено в нижнее with the help of this answer.
Ссылки:
Что вы имеете в виду с "быстрым"? Скорость выполнения? У вас есть большой объем данных или ** XML-> C# -> JSON ** - это опция? Где «специальный формат», о котором вы говорите? Быстро писать? Необработанный ** XML-считыватель ** (с текстовым потоком в качестве вывода) является самым быстрым способом, который я могу себе представить, но он менее подходит для повторного использования; ** LINQ to XML ** с сериализатором _custom_ JSON это довольно тривиально, но производительность не будет хорошей (для большого объема данных). Наконец, почему вы не используете ** XSLT **? Опять же, если у вас нет большого количества данных, это самое простое и гибкое решение. –
@Adriano. Xml не такой большой, не более 400 или 500 строк. Я знаю, моя проблема - сериализатор, но чтобы иметь возможность сериализовать, я должен знать, как разбирать XML. Я хотел бы использовать LINQ to XML, так как я немного работал с LINQ to SQL, но пока не знаю, какой метод (ы) использовать и как это сделать (если я прочитал некоторые вещи об этом, я сделай это сам, но мне нужно это быстрее, вот почему я прошу некоторых ведет). И да, XML для Json - мой единственный вариант, поскольку связь между клиентом и сервером - это только Json. Мой «специальный формат», на который я ссылался, является структурой строки Json.Thanq you :) – darkdante
Это неэффективно, но файл довольно маленький: взгляните на ** XSD ** (http://msdn.microsoft.com). /en-us/library/x6c1kb0s(v=vs.100).aspx). Он будет генерировать классы C# для чтения XML-файла, который вы предоставляете. Затем просто напишите свой собственный JSON _serializer_ (или используйте ** встроенный ** один). –