概要:
我知道这是一篇很长的阅读材料。总结一下,我需要每种语言下不在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>");
}
整个故事:
我正在尝试使用Linq读取一个以Excel导出的XML文件。我能够获取数据,但无法使其正常工作以将列与正确的行单元格对齐。
在发布代码之前,我应该提到一些事情。这个程序旨在读取任意数量的文件,它们可能有多种语言(第二行)。在这个特定的例子中,有两种语言,但在将来可能会有1种语言、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>
第一种语言的索引属性告诉您它从哪里开始,合并跨度告诉您它跨越了多少列。后续的语言仅包含合并跨越值,这些值告诉您每种语言之后跨越了多少列。
首先,这是两行示例数据的截图。
(下载的图像分辨率更高)
以下是第一行对应的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>
我需要从给定的XML文件中提取3个值:
名称和前缀,它们不是语言的一部分,并且始终存在,获取它们不是问题。
任何在语言列下不包含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
是一个简单的类,它只包含第一种语言的列,当前语言的起始列和当前语言的结束列。
我相信以上的代码是正确的。它可以读取所有值,并正确识别每种语言的起始和结束位置,问题就像帖子前面描述的那样。