2013-02-25 5 views
3

Резюме:Чтение XML-файл с Linq

Я знаю, что это долго читать. Подводя итог, мне нужно имя, префикс и все значения на каждом языке, которые не находятся в столбце documentation. И мне также нужно запомнить, на каком языке каждый ярлык приписывается.

Моя проблема:

Считывание данных и сохранить его с его собственно колонка - в основном, если есть пустое значение, он бросает все прочь. В примере Excel выше, для заготовки японского лейбла, и следующий код будет фактически двигаться gl-plt в label колонке:

for(int t=0; t<labelLinkValues.Count; t+=labelLinkCol.Count) { 

    for(int j=0; j<labelLinkCol.Count; j++) { 
     if(labelLinkCol[j].Value=="prefix") 
      Response.Write(labelLinkValues[t+j].Value+"<br/>"); 

     if(labelLinkCol[j].Value=="name") 
      Response.Write(labelLinkValues[t+j].Value+"<br/>"); 

     for(int p=0; p<langList.Count; p++) { 
      if(j>=langList[p].start&&j<=langList[p].end) 
       if(labelLinkCol[j].Value!="documentation"&&labelLinkValues[j].Value!="") 
        Response.Write(langList[p].languageValue+"---"+labelLinkValues[t+j].Value+"<br/>"); 
     } 

    } 

    Response.Write("----<br>"); 
} 

Вся история:

Я пытаюсь читать excel экспортированный файл XML с Linq. Я могу получить данные, но я не могу заставить его правильно работать с выравниванием столбцов с соответствующей ячейкой строки.

Прежде чем опубликовать код, я должен упомянуть некоторые вещи. Эта программа предназначена для чтения любого количества файлов, они могут иметь несколько языков (вторая строка). В этом конкретном примере существуют два языка, но в будущем может быть один язык, 3 языка, например. Языки определяются следующим образом:

<Row ss:AutoFitHeight="0"> 
    <Cell ss:StyleID="ColumnHead2" ss:Index="4" ss:MergeAcross="1"> 
     <ss:Data ss:Type="String">en</ss:Data> 
    </Cell> 

    <Cell ss:StyleID="ColumnHead2" ss:MergeAcross="1"> 
     <ss:Data ss:Type="String">ja</ss:Data> 
    </Cell> 
</Row> 

Атрибут Индекс первого языка говорит вам, где она начинается и слияние через говорит вам, сколько столбцов она охватывает. Следующие языки содержат только объединение значений, которые показывают, сколько столбцов каждый язык охватывает.

Прежде всего, вот скриншот двух строк данных образца.

(разрешение выше из downloded изображения) enter image description here

А вот соответствующий XML-код для первой строки:

<Row ss:AutoFitHeight="0"> 
    <Cell ss:StyleID="NoBorderNumberCell"> 
     <ss:Data ss:Type="Number">1</ss:Data> 
    </Cell> 

    <Cell ss:StyleID="NoBorderCell"> 
     <ss:Data ss:Type="String">gl-cor</ss:Data> 
    </Cell> 

    <Cell ss:StyleID="NoBorderCell"> 
     <ss:Data ss:Type="String">account</ss:Data> 
    </Cell> 

    <Cell ss:StyleID="NoBorderCell"> 
     <ss:Data ss:Type="String">Tuple: parent container for account numbers and identifiers. No entry is made here, but each detail line may have multiple accounts assigned to it for reporting in different GAAPs, offsetting accounts in Japan</ss:Data> 
    </Cell> 

    <Cell ss:StyleID="NoBorderCell"> 
     <ss:Data ss:Type="String">Account Identifier</ss:Data> 
    </Cell> 

    <Cell ss:StyleID="NoBorderCell"> 
     <ss:Data ss:Type="String">タプル。勘定科目番号と識別子</ss:Data> 
    </Cell> 

    <Cell ss:StyleID="NoBorderCell"/> 

    <Cell ss:StyleID="NoBorderCell"> 
     <ss:Data ss:Type="String">gl-plt</ss:Data> 
    </Cell> 
</Row> 

Есть 3 значения, что мне нужно извлечение из данного файла XML:

Имя и префикс, которые не являются частью языков и являются всегда присутствующие, получение их не является проблемой.

Любое значение под колонкой языка, которая не говорит documentation. Поэтому мне нужно игнорировать documentation столбцы.

Теперь вот код у меня есть, чтобы прочитать выше:

XElement xdocument=XElement.Load(fpath); 
XNamespace ns="urn:schemas-microsoft-com:office:spreadsheet"; 
XNamespace docProperties="urn:schemas-microsoft-com:office:office"; 
XNamespace ss="urn:schemas-microsoft-com:office:spreadsheet"; 
XNamespace search="ss"; 

var labelLinkCol=(
    from worksheets in xdocument.Elements(ns+"Worksheet") 
    where (string)worksheets.Attribute(ss+"Name")=="Label Link" 
    from columnHead in worksheets.Descendants(ns+"Cell") 
    where (string)columnHead.Attribute(ss+"StyleID")=="ColumnHead" 
    select columnHead 
    ).ToList(); 

var langValues=(
    from worksheets in xdocument.Elements(ns+"Worksheet") 
    where (string)worksheets.Attribute(ss+"Name")=="Label Link" 
    from columnHead in worksheets.Descendants(ns+"Cell") 
    where (string)columnHead.Attribute(ss+"StyleID")=="ColumnHead2" 
    select columnHead 
    ).ToList(); 

var labelLinkValues=(
    from worksheets in xdocument.Elements(ns+"Worksheet") 
    where (string)worksheets.Attribute(ss+"Name")=="Label Link" 
    from columnHead in worksheets.Descendants(ns+"Cell") 
    where 
     (string)columnHead.Attribute(ss+"StyleID")!="ColumnHead" 
     && 
     (string)columnHead.Attribute(ss+"StyleID")!="ColumnHead2" 
     && 
     (string)columnHead.Attribute(ss+"StyleID")!="ColumnHead2BL" 
    select columnHead 
    ).ToList(); 

int index=0; 
List<language> langList=new List<language>(); 

for(int j=0; j<langValues.Count; j++) { 
    language languageXML=new language(); 

    //the first value has the index 
    if(j==0) { 
     index=Convert.ToInt32(langValues[j].Attribute(ss+"Index").Value); 
     languageXML.index=index; 
     languageXML.start=index; 
     languageXML.end=index+Convert.ToInt32(langValues[j].Attribute(ss+"MergeAcross").Value); 
     languageXML.languageValue=langValues[j].Value; 
    } 
    else { 
     //get the value of when the first language begins 
     languageXML.index=index; 

     //to get the beginning, get the end of the previous location and add 1 
     languageXML.start=langList[langList.Count-1].end+1; 

     //to get the last column, add the merge to the beginning 
     languageXML.end=languageXML.start+Convert.ToInt32(langValues[j].Attribute(ss+"MergeAcross").Value); 
     languageXML.languageValue=langValues[j].Value; 
    } 

    langList.Add(languageXML); 
    //Response.Write(languageXML.start + "--" + languageXML.end + "--" + languageXML.languageValue + "<br>"); 
} 

language простой класс, который содержит только столбец первого языка, начальный столбец текущего языка и окончание столбец текущего языка.

Я считаю, что приведенный выше код как звук. Он читает во всех значениях и правильно определяет начальное и конечное местоположение для каждого языка, и проблема такая, как описано в начале сообщения.

+0

Это ужасный формат XML. Не можете ли вы получить данные в лучшем формате? – svick

+0

Вы пробовали xsd.exe? если вы просто читаете все, что может быть намного проще, если он сможет правильно разобрать – jle

+0

К сожалению, нет другого способа получить данные, он предоставляется от клиента, который экспортирует его с листа Excel. Данные читаются довольно хорошо, это просто обработка пробелов, которые убивают меня в логике. –

ответ

0

Мне кажется, что вы делаете это более сложным, чем это должно быть. Недавно я работал над проектом, который требовал, чтобы пользователи копировали данные из Excel, которые читаются в виде XML-таблицы через буфер обмена, который затем отправляется через парсер и преобразуется в табличный формат.

Я нашел Spreadsheet Ссылка XML бесценным: http://msdn.microsoft.com/en-us/library/office/aa140066(v=office.10).aspx

Одна вещь, вы должны быть в курсе, и что я думаю, что является причиной ваших проблем является то, что сс: Индекс не с нуля (колонка 1 = индекс 1).

Это должно быть так же просто, как перебирать строки, а затем их ячейки и отслеживать индекс клеток. Вы также можете проверить, имеет ли требуемая ячейка дочерний элемент данных.

Смежные вопросы