Написание XSLT для извлечения определенных атрибутов из файла XML - PullRequest
1 голос
/ 21 декабря 2011

Это будет моя первая попытка написания XSLT, который действительно делает что-то значимое и помогает мне в работе.Я уже писал xpath xpression's и довольно хорошо с ними справился, просто нужно промокнуть ногами с XSLT, чтобы действительно начать готовить.В любом случае,

У меня есть файл XML, в котором есть определенные узлы с атрибутами value.Я хочу, чтобы все узлы с атрибутами name распечатывали их атрибуты value в текстовом файле ...

Вот что у меня есть ... Пример XML

<?xml version="1.0"?>
<dataTemplateSpecification>
<templates>
<template>
  <elements>
    <element id="element0" name="PatientId" display="Patient ID" dataType="String" visable="true" readOnly="false" value="207">
      <mapping path="//Template/TemplateData/ACOData/PATIENT_ID" />
      <validation>
        <rules>
          <rule id="r0" test="#element0.value == ''">
            <fail>
              <html>
                <b>Patient ID is null, value must be present</b>
              </html>
            </fail>
          </rule>
        </rules>
      </validation>
    </element>
    <element id="element1" name="EncounterId" display="Encounter ID" dataType="String" visable="true" readOnly="false" value="144">
      <mapping path="//Template/TemplateData/ACOData/FOCUSED_READMISSIONS_ID" />
      <validation>
        <rules>
          <rule id="r0" test="#element0.value == ''">
            <fail>
              <html>
                <b>Patient ID is null, value must be present</b>
              </html>
            </fail>
          </rule>
        </rules>
      </validation>
    </element>
    </template></template></dataTemplateSpecification>

Вот самый базовый XSLT, который я написал ...

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="text" indent="yes"/>

<xsl:template match="//dataTemplateSpecification/templates/template/elements/element[@name=*]">
    <xsl:copy>
        <xsl:apply-templates select="@value"/>
    </xsl:copy>
</xsl:template>

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

Ответы [ 4 ]

2 голосов
/ 22 декабря 2011

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

<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="element[@name and @value]">
     <element>
       <xsl:value-of select=
        "concat(@name, ': ', @value)"/>
     </element>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному XML (исправлено несколько раз, чтобы сделать его правильно сформированным):

<dataTemplateSpecification>
    <templates>
        <template>
            <elements>
                <element id="element0" name="PatientId" display="Patient ID" dataType="String" visable="true" readOnly="false" value="207">
                    <mapping path="//Template/TemplateData/ACOData/PATIENT_ID" />
                    <validation>
                        <rules>
                            <rule id="r0" test="#element0.value == ''">
                                <fail>
                                    <html>
                                        <b>Patient ID is null, value must be present</b>
                                    </html>
                                </fail>
                            </rule>
                        </rules>
                    </validation>
                </element>
                <element id="element1" name="EncounterId" display="Encounter ID" dataType="String" visable="true" readOnly="false" value="144">
                    <mapping path="//Template/TemplateData/ACOData/FOCUSED_READMISSIONS_ID" />
                    <validation>
                        <rules>
                            <rule id="r0" test="#element0.value == ''">
                                <fail>
                                    <html>
                                        <b>Patient ID is null, value must be present</b>
                                    </html>
                                </fail>
                            </rule>
                        </rules>
                    </validation>
                </element>
            </elements>
        </template>
    </templates>
</dataTemplateSpecification>

желаемый, правильный результат получается :

<element>PatientId: 207</element>
<element>EncounterId: 144</element>
1 голос
/ 21 декабря 2011

Что-то вроде этого возможно:

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

<xsl:output method="text"/>

<xsl:variable name='newline'><xsl:text>
</xsl:text></xsl:variable>

<xsl:template match="//elements">
  <xsl:for-each select="//element[@name]">
    <xsl:value-of select="concat(@value,$newline)"/>
  </xsl:for-each>
</xsl:template>
</xsl:stylesheet>
1 голос
/ 21 декабря 2011

Ваш предикат XPath не делает то, о чем вы думаете. * - это селектор для всех дочерних элементов, а не шаблон с подстановочными знаками строки. Я предполагаю, что вы скорее хотите что-то подобное (все элементы element, которые имеют атрибут name и value):

//element[@name and @value]

А для распечатки значений атрибутов вам может потребоваться посмотреть xsl:value-of вместо xsl:copy и xsl:apply-templates, если вы не хотите фактически скопировать элемент.

0 голосов
/ 21 декабря 2011

На самом деле это было не так уж и плохо. Для первого XSLT я бы не попросил намного проще. то, что я написал ранее, будет почти работать. Но для этого мне нужно было бы написать

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="text" indent="yes"/>

<xsl:template match="//dataTemplateSpecification/templates/template/elements/element">   
    <xsl:copy>
        <xsl:value-of select="@name"></xsl:value-of>: <xsl:value-of select="@value"/>
    </xsl:copy>
</xsl:template>

Это, кажется, работало довольно хорошо.

...