Как я могу вставить XML в документ Word без списков нумерации в одну последовательность?C#

Место общения программистов C#
Ответить
Anonymous
 Как я могу вставить XML в документ Word без списков нумерации в одну последовательность?

Сообщение Anonymous »

Я пытаюсь объединить несколько документов Word (.docx), используя OpenXML в C#. Само слияние работает, но у меня есть постоянная проблема с пронумерованными и пуленами списками. Второе
имеет цифры → все списки в объединенном файле становятся числами. < /li>
Если в первом документе есть цифры, а второй имеет пули → Все списки в объединенном файле становятся пулями. /> < /ul>
Кажется, что в целевом документе < /strong> «strong>» в последнее время. Документ. < /li>
Создание новых атрибутов NSID и имен в списке, чтобы избежать столкновений. < /li>
Образцы отслеживания с словарями для Numid и Abstractnumid. < /li>
Обеспечение начального оборудования. Магия происходит в numberHelper.mycodeHelper ()
. Я хотел бы избежать публикации всего этого кода и просто дать мой вывод XML для каждого источника и нумерацию. Xml целевого документа, и, возможно, кто -то сможет сказать мне, где я ошибаюсь, потому что, как я понимаю, XML не имеет никаких явных идентификационных выпусков. var targetDoc = targetWml
NumberHelper.ResetGlobalMaps();
foreach (var sourceDoc in sourceDocs)
{
var result = NumberHelper.MyCodeHelper(WordprocessingDocument sourceDoc, WmlDocument targetDoc);
targetDoc = result.UpdatedDoc;
updatedParagraphs = result.UpdatedParagraphs;

//I then have some code here that I am using to insert the result.UpdatedPargraphs into the targetDoc. This code is not having any issues. It is a numbering.xml issue, I am almost certain.

}


source1 xml, который я вставляю и изображает его появление в документе.













This is atest

















asdfads

















fasdfasdfad

















fasdfads

















asdfasdf

















asdfasdfsdf

















asdfdsaf

















adsfasdfasdf

















asdfasdfasdf

















asdfadsfasdfdsafasdf



source2 xml, который я вставляю и изображает его появление в документе.













This iadfasdf adf

















asdfasd

















fasdfasdf

















asdfasdfasd

















fasdfasd

















fadsafs

















adsfasdfasd

















asdfa

















sdfasdfadsf

















asdfsdf


< /code>
Результаты - как он появляется в окончательном документе. РЕДАКТИРОВАТЬ: Удал окончательный документ XML для публикации кода ниже:

edit:
ЗДЕСЬ. Я должен удалить вывод XML, который я получаю, чтобы опубликовать это. < /P>
public static class NumberingHelper
{
// Maps (docId, srcAbsId, signature) → mapped abstractNumId
private static readonly Dictionary GlobalAbstractNumIdMap
= new Dictionary();

// Maps (docId, srcNumId, signature) → mapped numId
private static readonly Dictionary GlobalNumIdMap
= new Dictionary();

// Maps srcNumId → absSignature (per document, temporary)
private static readonly Dictionary SrcNumToAbsSignature
= new Dictionary();

private static int maxAbsNumId = 0;
private static int maxNumId = 0;

public static void ResetGlobalMaps()
{
GlobalAbstractNumIdMap.Clear();
GlobalNumIdMap.Clear();
SrcNumToAbsSignature.Clear();
}

public static NumberingResult CopyNumberingAndParagraphs(
WordprocessingDocument sourceDoc,
WmlDocument targetWml)
{
XNamespace w = "http://schemas.openxmlformats.org/wordp ... /2006/main";
//XNamespace w = "";

byte[] targetBytes = targetWml.DocumentByteArray;

// 1) Load source numbering
XDocument sourceNumbering = null;
if (sourceDoc?.MainDocumentPart?.NumberingDefinitionsPart != null)
{
using (var reader = new StreamReader(sourceDoc.MainDocumentPart.NumberingDefinitionsPart.GetStream()))
{
sourceNumbering = XDocument.Load(reader);
}
}

if (sourceNumbering == null)
return new NumberingResult { UpdatedDoc = targetWml, UpdatedParagraphs = new List() };

// 2) Load target numbering (or create new)
XDocument targetNumbering;
using (var msLoad = new MemoryStream(targetBytes))
using (var wDocLoad = WordprocessingDocument.Open(msLoad, false))
{
var mainPart = wDocLoad.MainDocumentPart;
var numberingPart = mainPart.NumberingDefinitionsPart;
if (numberingPart != null)
{
using (var reader = new StreamReader(numberingPart.GetStream()))
targetNumbering = XDocument.Load(reader);
}
else
{
targetNumbering = new XDocument(
new XElement(w + "numbering",
new XAttribute(XNamespace.Xmlns + "w", w.NamespaceName)));
}
}

// 3) Determine max IDs in target numbering
int maxAbsNumId = targetNumbering.Descendants(w + "abstractNum")
.Select(a => (int?)a.Attribute(w + "abstractNumId"))
.DefaultIfEmpty(0)
.Max() ?? 0;

int maxNumId = targetNumbering.Descendants(w + "num")
.Select(n => (int?)n.Attribute(w + "numId"))
.DefaultIfEmpty(0)
.Max() ?? 0;

// Unique prefix for this source doc instance
string docGuid = (sourceDoc?.PackageProperties?.Identifier) ?? Guid.NewGuid().ToString("N");

var srcNumToAbsSignature = new Dictionary();

// 4) Copy elements from source
foreach (var srcNum in sourceNumbering.Descendants(w + "num"))
{
var numAttr = srcNum.Attribute(w + "numId");
if (numAttr == null || !int.TryParse(numAttr.Value, out int srcNumId))
continue;

var absElem = srcNum.Element(w + "abstractNumId");
if (absElem == null)
continue;

var absAttr = absElem.Attribute(w + "val");
if (absAttr == null || !int.TryParse(absAttr.Value, out int srcAbsId))
continue;

var srcAbs = sourceNumbering.Descendants(w + "abstractNum")
.FirstOrDefault(a =>
{
var aAttr = a.Attribute(w + "abstractNumId");
return aAttr != null &&
int.TryParse(aAttr.Value, out int v) &&
v == srcAbsId;
});

if (srcAbs == null)
continue;

// Build unique signature
string absSignature = string.Join("|",
new[] {
(string)srcAbs.Element(w + "multiLevelType")?.Attribute(w + "val") ?? "",
(string)srcAbs.Element(w + "nsid")?.Attribute(w + "val") ?? ""
}
.Concat(
srcAbs.Elements(w + "lvl").Select(l =>
$"{(int?)l.Attribute(w + "ilvl") ?? -1}-" +
$"{(string)l.Element(w + "numFmt")?.Attribute(w + "val") ?? ""}-" +
$"{(string)l.Element(w + "lvlText")?.Attribute(w + "val") ?? ""}-" +
$"{(string)l.Element(w + "lvlJc")?.Attribute(w + "val") ?? ""}-" +
$"{(string)l.Element(w + "isLgl")?.Attribute(w + "val") ?? ""}"
)
)
);

var absKey = ((docGuid, srcAbsId), absSignature + "|" + docGuid);

if (!GlobalAbstractNumIdMap.TryGetValue(absKey, out int mappedAbsId))
{
var clonedAbs = new XElement(srcAbs);

mappedAbsId = ++maxAbsNumId;
clonedAbs.SetAttributeValue(w + "abstractNumId", mappedAbsId);

// generate fresh nsid
var newNsid = Guid.NewGuid().ToString("N").Substring(0, 8).ToUpperInvariant();
var nsidElem = clonedAbs.Element(w + "nsid");
if (nsidElem != null) nsidElem.SetAttributeValue(w + "val", newNsid);
else clonedAbs.Add(new XElement(w + "nsid", new XAttribute(w + "val", newNsid)));

// give it its own name
var nameElem = clonedAbs.Element(w + "name");
if (nameElem != null) nameElem.SetAttributeValue(w + "val", $"List_{newNsid}");
else clonedAbs.Add(new XElement(w + "name", new XAttribute(w + "val", $"List_{newNsid}")));

// ensure multiLevelType is preserved
var multiElem = srcAbs.Element(w + "multiLevelType");
if (multiElem != null)
clonedAbs.Add(new XElement(w + "multiLevelType",
new XAttribute(w + "val", multiElem.Attribute(w + "val")?.Value)));

targetNumbering.Root.Add(clonedAbs);
GlobalAbstractNumIdMap[absKey] = mappedAbsId;
}

int newNumForThis = ++maxNumId;
GlobalNumIdMap[(docGuid, srcNumId, absSignature)] = newNumForThis;
srcNumToAbsSignature[srcNumId] = absSignature;

var clonedNum = new XElement(srcNum);
clonedNum.SetAttributeValue(w + "numId", newNumForThis);

var absRefElem = clonedNum.Element(w + "abstractNumId");
if (absRefElem != null)
absRefElem.SetAttributeValue(w + "val", mappedAbsId);
else
clonedNum.Add(new XElement(w + "abstractNumId",
new XAttribute(w + "val", mappedAbsId)));

// Add lvlOverride resets
var mappedAbsElem = targetNumbering
.Descendants(w + "abstractNum")
.First(a => (int)a.Attribute(w + "abstractNumId") == mappedAbsId);

var ilvls = mappedAbsElem
.Elements(w + "lvl")
.Select(l => (int)l.Attribute(w + "ilvl"))
.ToList();

foreach (var i in ilvls)
{
var lo = clonedNum.Elements(w + "lvlOverride")
.FirstOrDefault(x => (int?)x.Attribute(w + "ilvl") == i);
if (lo == null)
{
lo = new XElement(w + "lvlOverride", new XAttribute(w + "ilvl", i));
clonedNum.Add(lo);
}
if (lo.Element(w + "startOverride") == null)
{
lo.Add(new XElement(w + "startOverride", new XAttribute(w + "val", 1)));
}
}

targetNumbering.Root.Add(clonedNum);
}

// 5) Update paragraphs
var updatedParagraphs = new List();
foreach (var para in sourceDoc.MainDocumentPart.Document.Body.Elements())
{
var paraClone = XElement.Parse(para.OuterXml);

var pPr = paraClone.Element(w + "pPr");
if (pPr == null)
{
pPr = new XElement(w + "pPr");
paraClone.AddFirst(pPr);
}

var numPr = pPr.Element(w + "numPr");
if (numPr == null)
{
numPr = new XElement(w + "numPr");
pPr.Add(numPr);
}

var numIdElem = numPr.Element(w + "numId");
if (numIdElem != null)
{
var valAttr = numIdElem.Attribute(w + "val");
if (valAttr != null && int.TryParse(valAttr.Value, out int originalNumId))
{
if (srcNumToAbsSignature.TryGetValue(originalNumId, out string absSignature))
{
if (GlobalNumIdMap.TryGetValue((docGuid, originalNumId, absSignature), out int mappedNumId))
{
// copy ilvl from source paragraph
var srcIlvlElem = paraClone.Descendants(w + "ilvl").FirstOrDefault();
if (srcIlvlElem != null)
{
var ilvlVal = srcIlvlElem.Attribute(w + "val")?.Value ?? "0";
var numPrIlvl = numPr.Element(w + "ilvl");
if (numPrIlvl != null)
numPrIlvl.SetAttributeValue(w + "val", ilvlVal);
else
numPr.Add(new XElement(w + "ilvl", new XAttribute(w + "val", ilvlVal)));
}

// set mapped numId
numIdElem.SetAttributeValue(w + "val", mappedNumId);
}
}
}
}

updatedParagraphs.Add(paraClone);
}

// 6) Save updated numbering.xml
using (var ms = new MemoryStream())
{
ms.Write(targetBytes, 0, targetBytes.Length);
ms.Position = 0;
using (var wDoc = WordprocessingDocument.Open(ms, true))
{
var mainPart = wDoc.MainDocumentPart;
var numberingPart = mainPart.NumberingDefinitionsPart ??
mainPart.AddNewPart();

using (var partStream = numberingPart.GetStream(FileMode.Create, FileAccess.Write))
{
targetNumbering.Save(partStream);
}

mainPart.Document.Save();
}

ms.Position = 0;
targetWml = new WmlDocument(targetWml.FileName, ms.ToArray());
}

return new NumberingResult
{
UpdatedDoc = targetWml,
UpdatedParagraphs = updatedParagraphs
};
}
}


Подробнее здесь: https://stackoverflow.com/questions/787 ... ing-into-o
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»