Как я могу получить самозакрывающиеся теги в выходном XML-файле с помощью XslCompiledTransform?

#xml #xslt #transform #xslcompiledtransform

#xml #xslt #преобразовать #xslcompiledtransform

Вопрос:

Пожалуйста, помогите мне…

У меня есть входной XML-документ:

 <?xml version="1.0" encoding="utf-8"?>
<Root>
    <Object>
      <GUID>201110180954525010129</GUID>
      <Meta name="FILENAME" format="string" frate="" />
    </Object>
</Root>
  

Мне нужно преобразовать его в следующий xml:

 <?xml version="1.0" encoding="UTF-8"?>
<Root> 
    <Object> 
        <GUID>201110180954525010129</GUID>
        <FILENAME/> 
    </Object>
<Root>
  

Я создал следующую таблицу стилей:

 <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:template match="/">
<xsl:element name="Root">

<xsl:for-each select="Root/Object">
<xsl:element name="Object">

<xsl:element name="FILENAME">
        <xsl:value-of select="Meta[@name='FILENAME']" />
</xsl:element>

<xsl:element name="GUID">
        <xsl:value-of select="GUID" />
</xsl:element>

</xsl:element>
</xsl:for-each>

</xsl:element>
</xsl:template>
</xsl:stylesheet>
  

Но когда я пытаюсь преобразовать его, я получаю следующий результат:

 <?xml version="1.0" encoding="UTF-8"?>
<Root> 
    <Object> 
    <GUID>201110180954525010129</GUID>
        <FILENAME> </FILENAME> 
    </MAObject>
<Root>
  

Как я могу указать, как интерпретировать самозакрывающиеся теги?

Код преобразования C #:

         var stylesheet = "styleSheet.xml";
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.Load("input.xml");
        XslCompiledTransform xslTransform = new XslCompiledTransform();
        xslTransform.Load(styleSheet);

            XmlDocument xmlDocumentOutput = new XmlDocument();
            XmlDeclaration xmlDocumentOutputDeclaration = xmlDocumentOutput.CreateXmlDeclaration("1.0", "utf-8", null);
            xmlDocumentOutput.AppendChild(xmlDocumentOutputDeclaration);

            using (XmlWriter xmlWriter = xmlDocumentOutput.CreateNavigator().AppendChild())
            {
                xslTransform.Transform(xmlDocument.CreateNavigator(), null, xmlWriter);
            }

            return xmlDocumentOutput;
  

Ответ №1:

Я попробовал наши образцы с помощью XslCompiledTransform, результат, который я получаю,

 <Root>
  <Object>
    <FILENAME></FILENAME>
    <GUID>201110180954525010129</GUID>
  </Object>
</Root>
  

Как вы точно выполняете преобразование, как вы смотрите на результат?
В XML пустой элемент «foo» может быть помечен как <foo></foo> или <foo/> или <foo /> , эти формы семантически эквивалентны. Зачем вам нужна конкретная форма? Является ли вывод преобразования XSLT не обработанным синтаксическим анализатором XML?

[редактировать] Попробуйте ли заменить

 <xsl:element name="FILENAME">
        <xsl:value-of select="Meta[@name='FILENAME']" />
</xsl:element>
  

с помощью

 <FILENAME>
  <xsl:if test="normalize-space(Meta[@name='FILENAME'])">
    <xsl:value-of select="Meta[@name='FILENAME']"/>
  </xsl:if>
</FILENAME>
  

по крайней мере, убедитесь, что элемент FILENAME, который вы получаете, пуст.

Комментарии:

1. Привет! Спасибо за ответ. Я только что обновил вопрос… Я действительно не понимаю, почему я получаю пробелы между тегами <FILENAME> </FILENAME>

Ответ №2:

Попробуйте удалить разрывы строк (и любые другие пробелы) <xsl:value-of> в соответствующем шаблоне FILENAME . Это текстовые узлы, которые отображаются в результате.

Ответ №3:

Я не знаю, будет ли это иметь какое-либо значение, но попробуйте эту таблицу стилей, в которой есть отдельные соответствующие шаблоны для метаданных с данными и без данных. Во всяком случае, он построен на шаблоне identity и, таким образом, устраняет необходимость в жестком кодировании такого количества имен элементов в вашем исходном XSLT

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="Meta">
      <xsl:element name="{@name}" />
   </xsl:template>

   <xsl:template match="Meta[. != '']">
      <xsl:element name="{@name}">
         <xsl:apply-templates select="node()"/>
      </xsl:element>
   </xsl:template>

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

Когда я тестирую это, я получаю следующий результат:

 <Root>
   <Object>
      <GUID>201110180954525010129</GUID>
      <FILENAME/>
   </Object>
</Root>