您知道有什么XML库可以基于原始的未标记文本在XML标记与字符范围或偏移信息之间进行相互转换吗?(我不太关心这些库的基础平台:它可以是Java、Python、Perl等)。
例如,假设我有这样一个未标记的文本:
the calico cat and the black dog它被标记为
the <PET>calico</PET> cat and the <PET>black do</PET>g标记有位置错误(如上所述)。我知道如何修复这些错误:这不是这里的问题。但是使用传统的具有层次结构的XML解析器来做这件事是相当痛苦的。如果将XML标记转换为我可以轻松调整的带外字符范围,将会更容易:
PET: 4-10 # "calico" (should be 4-14 "calico cat" )
PET: 23-31 # "black do" (should be 23-32 "black dog" )在修复偏移量之后,我将重新生成XML。
我只找到了几个返回字符偏移量信息的XML解析库,偏移量是基于XML文本的,而不是未标记的文本。此外,偏移量也可能是错误的(参见Java, XMLEvent location Characters)。
发布于 2013-04-23 04:50:48
下面是如何在.NET中使用XmlReader来完成此操作:
class MarkupSpan
{
internal string Name;
internal int Start;
internal int Stop;
internal List<object> ChildItems;
internal MarkupSpan(string name, int start)
{
Name = name;
Start = start;
ChildItems = new List<object>();
}
public override string ToString()
{
return string.Concat(ChildItems);
}
}
private static string ProcessMarkup(string text)
{
Stack<MarkupSpan> inputStack = new Stack<MarkupSpan>();
StringReader sr = new StringReader("<n>" + text + "</n>");
XmlReader xr = XmlReader.Create(sr);
int pos = 0;
StringBuilder output = new StringBuilder();
while (xr.Read())
{
if (xr.Depth > 0)
{
switch (xr.NodeType)
{
case XmlNodeType.Text:
pos += xr.Value.Length;
if (inputStack.Count != 0)
{
inputStack.Peek().ChildItems.Add(xr.Value);
}
break;
case XmlNodeType.Element:
MarkupSpan ms = new MarkupSpan(xr.LocalName, pos);
if (inputStack.Count != 0)
{
inputStack.Peek().ChildItems.Add(ms);
}
inputStack.Push(ms);
break;
case XmlNodeType.EndElement:
ms = inputStack.Pop();
ms.Stop = pos;
if (inputStack.Count == 0)
{
output.Append(OutputSpan(ms));
}
break;
}
}
}
return output.ToString();
}
private static string OutputSpan(MarkupSpan ms)
{
string nameAndRange = string.Format("{0}: {1}-{2}",
ms.Name, ms.Start, ms.Stop);
return string.Format("{0,-14}# \"{1}\"", nameAndRange, ms) +
Environment.NewLine +
string.Concat(ms.ChildItems.OfType<MarkupSpan>().Select(OutputSpan));
}在样例输入上运行时,结果为:
PET: 4-10 # "calico"
PET: 23-31 # "black do"当在一个更有趣的例子上运行时(带有嵌套标签):
the <PET><COLOR>calico</COLOR></PET> cat and the <PET><COLOR>bla</COLOR>ck do</PET>g结果是:
PET: 4-10 # "calico"
COLOR: 4-10 # "calico"
PET: 23-31 # "black do"
COLOR: 23-26 # "bla"发布于 2013-04-23 03:56:17
你反对.NET吗?
您可能希望从HTML的角度来处理这个问题。有一个叫做HtmlAgilityPack的库可以解析超文本标记语言(不管怎么说,它只是一个XML )。这样,您的示例看起来就像一个节点列表,分为文本节点和超文本标记语言( PET )节点:
HtmlNode[n]
|
+--[0] "the " (text node)
|
+--[1] <PET>
| |
| +--[0] "calico" (text node)
|
+--[2] " cat and the " (text node)
|
+--[3] <PET>
| |
| +--[0] "black do" (text node)
|
+--[4] "g" (text node)每个HtmlNode对象都有一个LinePosition属性,该属性将为您提供起始偏移量。末端偏移量可以通过添加节点的文本长度( InnerText属性)或从下一个节点的LinePosition中减去1来计算。
我不知道您是否认为这种方法不那么痛苦,但这是我要开始的地方(我以前从未解决过这样的问题)。
这里有各种语言的的超文本标记语言解析库。
发布于 2013-04-23 05:11:45
我已经提供了一个.NET的答案,但下面是如何使用XSLT实现的:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:variable name="space" select="' '" />
<xsl:variable name="spaceLen" select="string-length($space)" />
<xsl:template match="text()" />
<xsl:template match="*/*">
<xsl:param name="parentLeading" select="0" />
<xsl:variable name="leadingText">
<xsl:apply-templates select="preceding-sibling::node()" mode="value" />
</xsl:variable>
<xsl:variable name="leading" select="$parentLeading +
string-length($leadingText)" />
<xsl:variable name="nameAndRange"
select="concat(local-name(), ' ', $leading,
'-', $leading + string-length())" />
<xsl:variable name="spacing"
select="substring($space, 1, 14 - string-length($nameAndRange))" />
<xsl:value-of select="concat($nameAndRange, $spacing,
'# "', ., '"
')"/>
<xsl:apply-templates>
<xsl:with-param name="parentLeading" select="$leading" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="node()" mode="value">
<xsl:value-of select="." />
</xsl:template>
</xsl:stylesheet>在此输入上运行时:
<n>the <PET>calico</PET> cat and the <PET>black do</PET>g</n>结果是:
PET 4-10 # "calico"
PET 23-31 # "black do"在此输入上运行时:
<n>the <PET><COLOR>calico</COLOR></PET> cat and the <PET><COLOR>bla</COLOR>ck do</PET>g</n>结果是:
PET 4-10 # "calico"
COLOR 4-10 # "calico"
PET 23-31 # "black do"
COLOR 23-26 # "bla"https://stackoverflow.com/questions/16155481
复制相似问题