2013-01-15 2 views
3

Я новичок в XML, так как теперь я работал только с Json :( У меня есть XML-файл, который выглядит следующим образом:.C#/Net -Fast способ Разобрать XML/XML -> Json

<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> 

Я хочу, чтобы разобрать его в 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'} 
]} 

Моя проблема заключается в том, что я не работал с XML вообще (да, позор мне) Могли бы вы пожалуйста, дайте мне несколько советов о том, как быстро анализировать xml (у меня это есть на Stream, я загрузил его на сервер). У меня есть поисковик d для некоторых конвертеров XML для Json, но невозможно удовлетворить то, что мне нужно, так как мне нужен «специальный» формат.

Благодарим за ответы :)! Я использую C#.

+0

Что вы имеете в виду с "быстрым"? Скорость выполнения? У вас есть большой объем данных или ** XML-> C# -> JSON ** - это опция? Где «специальный формат», о котором вы говорите? Быстро писать? Необработанный ** XML-считыватель ** (с текстовым потоком в качестве вывода) является самым быстрым способом, который я могу себе представить, но он менее подходит для повторного использования; ** LINQ to XML ** с сериализатором _custom_ JSON это довольно тривиально, но производительность не будет хорошей (для большого объема данных). Наконец, почему вы не используете ** XSLT **? Опять же, если у вас нет большого количества данных, это самое простое и гибкое решение. –

+0

@Adriano. Xml не такой большой, не более 400 или 500 строк. Я знаю, моя проблема - сериализатор, но чтобы иметь возможность сериализовать, я должен знать, как разбирать XML. Я хотел бы использовать LINQ to XML, так как я немного работал с LINQ to SQL, но пока не знаю, какой метод (ы) использовать и как это сделать (если я прочитал некоторые вещи об этом, я сделай это сам, но мне нужно это быстрее, вот почему я прошу некоторых ведет). И да, XML для Json - мой единственный вариант, поскольку связь между клиентом и сервером - это только Json. Мой «специальный формат», на который я ссылался, является структурой строки Json.Thanq you :) – darkdante

+0

Это неэффективно, но файл довольно маленький: взгляните на ** XSD ** (http://msdn.microsoft.com). /en-us/library/x6c1kb0s(v=vs.100).aspx). Он будет генерировать классы C# для чтения XML-файла, который вы предоставляете. Затем просто напишите свой собственный JSON _serializer_ (или используйте ** встроенный ** один). –

ответ

2

я должен был написать на заказ решения для того же типа вещей сам недавно. Я сделал это с помощью 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,'&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> 

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.

Ссылки:

+0

Thanq you, Codesleuth :) – darkdante

+0

Добро пожаловать! Полагаю, это сработало для вас? – Codesleuth

-3
XDocument xDoc = XDocument.Load(queryURL);        
var x1 = from el in xDoc.Root.Descendants("results").Descendants("div").Descendants("div").Descendants("span").Attributes("class") 
where el.Value == "pr" 
    select el.Parent.Value;     
    stockFeed.Price = Decimal.Parse(x1.First().ToString()); 

LINQ - это лучший способ извлечь данные.

0

Использование класса 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); 

Документация здесь: Converting between JSON and XML with Json.NET

+0

Я уже пробовал это, но, похоже, у меня нет метода SerializeXmlNode в Jayrock.Json.Conversion; – darkdante

+0

Библиотека jayrock.json.conversion не предназначена для конверсии, используйте этот пример здесь, например, также http://james.newtonking.com/projects/json/help/ вы можете скачать его с http: //json.codeplex. com/ – Meherzad