Как насчет того, чтобы использовать этот "дополнительный" метод на XElement? работавший для меня!
public static string InnerXml(this XElement element)
{
StringBuilder innerXml = new StringBuilder();
foreach (XNode node in element.Nodes())
{
// append node's xml string to innerXml
innerXml.Append(node.ToString());
}
return innerXml.ToString();
}
ИЛИ использование определенное примечание Linq
public static string InnerXml(this XElement element)
{
StringBuilder innerXml = new StringBuilder();
doc.Nodes().ToList().ForEach( node => innerXml.Append(node.ToString()));
return innerXml.ToString();
}
: код выше должен использовать element.Nodes()
в противоположность element.Elements()
. Очень важная вещь помнить различие между двумя. element.Nodes()
дает Вам все как XText
, XAttribute
и т.д., но XElement
только Элемент.
Из-за Microsoft Пространство имен SQL Reporting Services 2008, которое было частью входного XML. Сначала я не понял, что
был таким важная линия. Спасибо Павлу Минаеву за комментарий к пространству имен . Следующий XSL работал для извлечения данных, которые мне нужны:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="EXQC005">
<xsl:output method="xml" indent="yes" encoding="utf-8"/>
<xsl:template match="/">
<xsl:for-each select="a:Report/a:FlatData/a:Details1_Collection/a:Details1">
<xsl:element name="{name(.)}">
<xsl:for-each select="@*">
<xsl:element name="{name(.)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Я думаю, я попытаюсь очистить это, чтобы использовать стиль apply-templates
, который предложил lavinio . Также благодарим Йорна Хорстманна за select = "@ *" Код
в для каждого
цикла. Было бы интересно выяснить, почему отчеты служб Reporting Services изначально выгружаются со значением xmlns
, установленным в качестве имени отчета, а не URL схемы .
Я продолжайте обновлять этот ответ по мере того, как я уточняю этот XSL.
Изменить: вот версия, не зависящая от пространства имен, поскольку для каждого отдельного отчета из служб Reporting Services, очевидно, будет другое пространство имен:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="utf-8"/>
<xsl:template match="/">
<xsl:for-each select="*[local-name()='Report']/*[local-name()='FlatData']/*[local-name()='Details1_Collection']/*[local-name()='Details1']">
<Details>
<xsl:for-each select="@*">
<xsl:element name="{name(.)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</Details>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Чтобы решить проблему пространства имен (для обоих ответов), добавьте объявление пространства имен с префиксом в свой XLST:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:r="MyReport"
version="1.0">
, а затем используйте его во всех своих выражениях XPath для определения элементов, например:
<xsl:template match="//r:Details1">
Вы можете использовать "@ *"
для ссылки на все атрибуты, как в этих примерах:
Конструкция
может использоваться для создания новый элемент с произвольным именем, а функции name ()
или local-name ()
вернут имя определенного атрибута.
Чтобы сделать то, что вы хотите, попробуйте что-то вроде этих строк:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<FlatData>
<Details1_Collection>
<xsl:apply-templates select="FlatData/Details1_Collection/Details1"/>
</Details1_Collection>
</FlatData>
</xsl:template>
<xsl:template match="Details1">
<Details1>
<xsl:apply-templates select="@*"/>
</Details1>
</xsl:template>
<xsl:template match="@*">
<xsl:element name="{name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Дает ли это преобразование желаемый результат?
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" encoding="utf-8" />
<xsl:template match="//Details1">
<Details1>
<xsl:for-each select="@*">
<xsl:element name="{name(.)}"><xsl:value-of select="." /></xsl:element>
</xsl:for-each>
</Details1>
</xsl:template>
</xsl:stylesheet>
Наверное, самый простой способ сделать это:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="/">
<FlatData>
<xsl:copy-of select="//Details1" />
</FlatData>
</xsl:template>
</xsl:stylesheet>
Другой способ написать ответ Йорна Хорстманна (если вам нужно сделать это с помощью Details1, Details2 и т. Д. ...) будет:
<xsl:template match="//Details1 | //Details2 | //whatever">
<xsl:copy>
<xsl:apply-templates select="@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:element name="{name(.)}">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>