2014-08-27 3 views
0

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

<Parent Value="x"> 
<!---->Unlimited number of child elements could exist with any value from 0-1 
    <Child Value="0.1"/> 
    <Child Value="1"/> 
    <Child Value="0.30"/> 
    ... 
</Parent> 

мне нужен родительский/дочерний узел вывода XML в следующем формате:

<Parent Value="x"> 
    <Child Value="0.3"/> 
</Parent> 

Где есть только один дочерний элемент и его значение постоянны на 0,3.

Мой текущий XSLT вид работ:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="yes" indent="yes"/> 

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

<xsl:template match="Parent"> 
    <Parent> 
     <xsl:apply-templates select="@*|*"/> 
     <Child Value="0.3"/> 
    </Parent> 
</xsl:template> 

<xsl:template match="Child[@Value!=0.3]"/> 

Я пытался создать нужный дочерний элемент во всех файлах (в случае, если он не существует)

<Child Value="0.3"/> 

, а затем выводить только дочерний элемент, если его значение = 0,3. Однако это иногда приводит к дублированию дочернего узла, и я чувствую, что, возможно, я не подхожу к этому правильно. Кроме того, заголовки xmlns: xs появляются после элемента «Родитель», а не в верхней части выходного документа. Любое руководство будет принята с благодарностью!

Пример выходного тока:

<Parent Value="x" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"> 
    <Child Value="0.30" /> 
    <Child Value="0.3" /> 
</Parent> 

ответ

2

Есть только две вещи, которые должны быть внесены изменения:

Используйте одинарные кавычки здесь:

<xsl:template match="Child[@Value!='0.3']"/> 

Если вы этого не сделаете, то это значение интерпретируется как числа, в противном случае в виде строки. Почему это имеет значение? Потому что, если правая часть выражения является числом, значение атрибута также преобразуется в число - и 0.3 и 0.30 в конечном итоге становятся одинаковыми. Который в конечном итоге приводит к выходу нескольких элементов Child.

Сделать преднамеренное введение в Child элемента условного, используя xsl:if. Остаточно, в зависимости от того, существует ли этот конкретный элемент во входе. Затем вы не получите два результата: Child.

Примечание. Любой дочерний узел Parent, который не является атрибутом или узлом элемента (то есть processing-instruction() и comment()), просто игнорируется в вашей таблице стилей. Это связано с тем, что вы применяете шаблоны только к @*|*, а не к @*|node().

стилевых

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="yes" indent="yes"/> 

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

<xsl:template match="Parent"> 
    <Parent> 
     <xsl:apply-templates select="@*|*"/> 
     <xsl:if test="not(Child[@Value = '0.3'])"> 
      <Child Value="0.3"/> 
     </xsl:if> 
    </Parent> 
</xsl:template> 

<xsl:template match="Child[@Value!='0.3']"/> 

</xsl:stylesheet> 

XML Input

<?xml version="1.0" encoding="UTF-8"?> 
<Parent Value="x"> 
    <Child Value="0.30"/> 
    <Child Value="1"/> 
    <Child Value="0.4"/> 
    <Child Value="0.3">The right one</Child> 
</Parent> 

XML Output

<Parent xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     xmlns:fn="http://www.w3.org/2005/xpath-functions" 
     xmlns:xdt="http://www.w3.org/2005/xpath-datatypes" 
     Value="x"> 
    <Child Value="0.3">The right one</Child> 
</Parent> 

В настоящее время существует ООН используемые пространства имен в вашем выходном XML. Вы можете запретить им появляться на выходе, добавив exclude-result-prefixes="#all" в xsl:stylesheet. Если вы это сделаете, то выход будет упрощен до

<Parent Value="x"> 
    <Child Value="0.3">The right one</Child> 
</Parent> 
+0

Не могу сказать, насколько это полезно! Это имеет смысл. Спасибо огромное! – lcf0285

0

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

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

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

<xsl:template match="Child"/> 

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

</xsl:stylesheet> 
Смежные вопросы