2010-11-22 4 views
1

Я работаю над проектом biztalk, и мне нужно скопировать (отфильтровать) содержимое от 1 xml к другому. Я должен сделать это с помощью xpath, я не могу использовать преобразование xsl. Так что мой XPath, чтобы получить содержимое из исходного файла XML заключается в следующем:xpath возвращает строку вместо nodelist

//*[not(ancestor-or-self::IN1_Insurance)]|//IN1_Insurance[2]/descendant-or-self::* 

Теперь это возвращает XmlNodeList. Можно ли вернуть строку со всеми узлами в нем нравится:

"<root><node>text</node></root>" 

Если я ставлю строку() перед моей XPath возвращает значения, но я хочу, чтобы весь XML в строке (с узлами ..), поэтому я мог загрузить эту строку в другой xmldocument. Я думаю, что это лучший метод для моей проблемы.

Я знаю, что могу перебирать xmlnodelist и добавлять узлы к новому xmldocument, но немного сложно петли в оркестровке biztalk, и я хочу этого избежать.

Код, который я могу использовать, это C#. Я попытался просто назначить нодлист в xmldocument, но это вызывает ошибку приведения (очевидно ..).

Как я вижу это, что у меня есть 2 решения:

  • присваивают нодлист к XmlDocument без петли (не возможно я думаю, что в C#)
  • каким-то образом преобразовать нодлист в строку и нагрузки это в XmlDocument
  • ТЕПЛОВОЙ нАГРУЗКИ непосредственно в XPath новой XmlDocument (не знаю, если это возможно, поскольку он возвращает нодлист)

Спасибо за вашу помощь

редактировать:

ввода пробы:

<root> 
<Patient> 
    <PatientId></PatientId> 
    <name></name> 
</Patient> 
<insurance> 
    <id>1</id> 
    <billing></billing> 
</insurance 
<insurance> 
    <id>2</id> 
    <billing></billing> 
</insurance> 
<insurance> 
    <id>3</id> 
    <billing></billing> 
</insurance> 
    </root> 

Теперь я хочу, чтобы скопировать этот образец другому XmlDocument, но без страхового узла 2 и 3 (это динамически, поэтому он может быть unsurance узел 1 и 2, чтобы удалить, или 1 и 3 ...)

Так что это должен быть выход:

<root> 
<Patient> 
    <PatientId></PatientId> 
    <name></name> 
</Patient> 
<insurance> 
    <id>1</id> 
    <billing></billing> 
</insurance> 
</root> 

Теперь я использую xpath, чтобы получить нужные узлы. Тогда я хочу, чтобы присвоить результат новой XmlDocument, но это не представляется возможным, так как я получаю castException

string xpath = "//*[not(ancestor-or-self::IN1_Insurance)]|//IN1_Insurance[2]/descendant-or-self::*"; 
xmlDoc = new System.Xml.XmlDocument(); 
xmlDoc = xpath(sourceXml, strXpath); <= cast error (cannot cast xmlnodelist to xmldocuemnt) 

Я знаю синтаксис немного странно, но это BizTalk C# код ..

+0

@Dimitre, это выглядит, как вы удалили XPath, и это понятно, но я не уверен, что здесь нет вопроса о XPath. Есть хороший шанс, что выражение XPath, используемое OP, неверно. – LarsH 2010-11-22 15:35:29

+0

@LarsH: Я отредактировал теги, потому что то, чего хочет OP, не может быть достигнуто только с XPath - или вы предлагаете поставить его под «not-xpath»? Кстати, вы проверили свой адрес электронной почты? – 2010-11-22 17:03:49

+1

@Dimitre: Я думаю, что тег xpath подходит по двум причинам: 1) вопрос «Можно ли это сделать с помощью XPath?» это полезный вопрос о XPath, даже если ответ «нет»; и 2), хотя эта задача не может быть выполнена только с XPath (не так много), ее можно было бы сделать с помощью XPath в сочетании с другими инструментами в среде, и в этом случае необходимо правильно получить выражение XPath. (Да, я скоро отвечу на электронную почту. :-) – LarsH 2010-11-22 17:23:07

ответ

3

Наиболее простым решением было бы «перебрать xmlnodelist и добавить (импортировать) узлы в новый xmldocument», но поскольку вы не можете зацикливаться, какие другие основные вещи вы можете/не можете сделать?

Чтобы сериализовать ноделист, вы можете попробовать использовать XmlNodeList.toString(). Если это сработает, вы получите странного зверя, потому что он может дублировать части документа XML несколько раз. Тем более, что вы явно включаете предков и потомков непосредственно в нодлист.Это не было бы чем-то, что вы могли бы отработать снова и получить результат, похожий на нодлист, с которого вы начали.

Другими словами, было бы лучше всего перебрать XmlNodeList и импортировать узлы в новый XmlDocument.

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

//*[not(ancestor-or-self::IN1_Insurance)]|//IN1_Insurance[2]/descendant-or-self:: 

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

Update:

Я понимаю, что вы пытаетесь сделать: скопировать документ XML, опуская все <insurance> элементы (и их потомков), за исключением того, который вы хотите.

Это может быть сделано без петли если выход столь же просто, как ваш выход образца: только один <Patient> и один <insurance> элемент, с их потомками, под одним элементом верхнего уровня.

Нечто подобное (я не могу проверить это, как я не имею сервера BizTalk):

string xpathPatient = "/*/Patient"; 
string xpathInsuran = "/*/insurance[id = " + insId + "]"; // insId is a parameter 
xmlDoc = new System.Xml.XmlDocument(); 
xmlPatient = xpath(sourceXml, xpathPatient); 
xmlInsuran = xpath(sourceXml, xpathInsuran); 
XmlElement rootNode = xmlDoc.CreateElement("root"); 
xmlDoc.AppendChild(rootNode); 
//**Update: use [0] to get an XmlNode from the returned XmlNodeList (presumably) 
rootNode.AppendChild(xmlDoc.ImportNode(xmlPatient[0], true)); 
rootNode.AppendChild(xmlDoc.ImportNode(xmlInsuran[0], true)); 

каюсь, хотя, мне очень интересно, почему вы не можете использовать XSLT. Вы приближаетесь к задачам, которые легче выполнять в XSLT, чем в XPath + C# XmlDocument.

Обновление:, так как функция XPath(), вероятно, возвращает XmlNodeList, а не XmlNode, я добавил [0] с первым аргументом ImportNode() выше. Спасибо @Martin Honnen за то, что предупредил меня об этом.

1

XPath - это язык запросов (только) для документов XML.

Он работает с абстрактной моделью - XML ​​INFOSET и не может ни изменять структуру XML-документа (ов), в котором он работает, либо упорядочивает информационные элементы INFOSET обратно в XML.

Таким образом, единственный способ добиться такой сериализации - использовать язык, на котором размещается XPath.

Помимо этого, есть очевидные проблемы с YOUT вопрос, например, это не ни один элемент с именем IN1_Insurance в предоставленном документе XML - поэтому выражение XPath при условии:

//*[not(ancestor-or-self::IN1_Insurance)]|//IN1_Insurance[2]/descendant-or-self::* 

выбирает все элементы документ.

Примечание:

Описанная задача элементарно выполнить с помощью XSLT.

Наконец: Если вам разрешено использовать C#, то вы можете использовать класс XslCompiledTransform (или XslTransform).Используйте свой метод Transform(), чтобы выполнить следующее преобразование против документа XML:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="insurance[not(id=1)]"/> 
</xsl:stylesheet> 

Это производит точно желаемый результат:

<root> 
    <Patient> 
     <PatientId></PatientId> 
     <name></name> 
    </Patient> 
    <insurance> 
     <id>1</id> 
     <billing></billing> 
    </insurance> 
</root> 
Смежные вопросы