XSLT: я пытаюсь сгладить элемент XML на основе имени дочернего элемента, используя XSLT 1.0 - PullRequest
1 голос
/ 05 марта 2012

пытаюсь сгладить элемент XML на основе имени дочернего элемента, используя XSLT 1.0

Исходный XML:

<Contact>
  <ContactPurpose>
    <PurposeAsPlainText xmlns="cds_dt">Call</PurposeAsPlainText>
  </ContactPurpose>
  <ContactPurpose>
    <PurposeAsEnum xmlns="cds_dt">Call</PurposeAsEnum>
  </ContactPurpose>
</Contact>

Должен быть преобразован в следующий XML:

<Contact>
  <ContactPurpose>O</ContactPurpose>
  <ContactPurpose>Call</ContactPurpose>
</Contact>

Логика:

ЕСЛИ имя дочернего элемента «PurposeAsPlainText», ТО установить «O» для «Другое» в месте назначения

ELSEIF, если имя дочернего элемента «PurposeAsEnum», ТО скопироватьисходное значение до места назначения

РЕДАКТИРОВАТЬ 1 : Я мог бы быть более ясным, поскольку ни одно из решений не сгладило XML, см. пересмотренный исходный и Dest XML.

РЕДАКТИРОВАТЬ 2 : Вот XML, с которым я тестировал.Два приведенных ниже решения для преобразования действительно работают с моим исходным xml, но не с пересмотренным xml, который я тестировал с помощью .NET 4.0 XslCompiledTransform.Или я должен задать новый вопрос?

<MyDS xmlns="cds" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <PatientRecord>
    <Demographics>
      <Contact>
        <ContactPurpose>
          <PurposeAsPlainText xmlns="cds_dt">Call</PurposeAsPlainText>
        </ContactPurpose>
        <ContactPurpose>
          <PurposeAsEnum xmlns="cds_dt">Call</PurposeAsEnum>
        </ContactPurpose>
      </Contact>
    </Demographics>
  </PatientRecord>
</MyDS>

Ответы [ 3 ]

1 голос
/ 06 марта 2012

Обновление: изменил ответ, чтобы соответствовать измененному исходному документу XML.

Описание не очень понятно, но я думаю, вы пытаетесь сделать вот что:

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

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

<xsl:template match="cds:ContactPurpose">
   <xsl:copy>
      <xsl:choose>
         <!-- when there is a child element PurposeAsPlainText
            in the cds_dt namespace: -->
         <xsl:when test="cds_dt:PurposeAsPlainText">0</xsl:when>
         <!-- I'm guessing that PurposeAsEnum is also supposed to be
            in the cds_dt namespace. -->
         <xsl:otherwise>
            <xsl:value-of select="cds_dt:PurposeAsEnum" />
         </xsl:otherwise>
      </xsl:choose>
   </xsl:copy>
</xsl:template>

</xsl:stylesheet>
1 голос
/ 06 марта 2012

Это можно сделать простым и коротким способом (без явных условий) :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:x="cds_dt" exclude-result-prefixes="x">
 <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="ContactPurpose/x:PurposeAsPlainText/text()">0</xsl:template>

 <xsl:template match="ContactPurpose/*"><xsl:apply-templates/></xsl:template>
</xsl:stylesheet>

применительно к следующему документу XML (расширен довключите оба интересующих случая):

<Contact>
    <ContactPurpose>
        <PurposeAsPlainText xmlns="cds_dt">Call</PurposeAsPlainText>
    </ContactPurpose>
    <ContactPurpose>
        <PurposeAsEnum xmlns="cds_dt">Call</PurposeAsEnum>
    </ContactPurpose>
</Contact>

дает требуемый, правильный результат :

<Contact>
   <ContactPurpose>0</ContactPurpose>
   <ContactPurpose>Call</ContactPurpose>
</Contact>

Объяснение :

Переопределение правила идентификации и правильное использование шаблонов / шаблонов совпадений.

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

<MyDS xmlns="cds" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <PatientRecord>
        <Demographics>
            <Contact>
                <ContactPurpose>
                    <PurposeAsPlainText xmlns="cds_dt">Call</PurposeAsPlainText>
                </ContactPurpose>
                <ContactPurpose>
                    <PurposeAsEnum xmlns="cds_dt">Call</PurposeAsEnum>
                </ContactPurpose>
            </Contact>
        </Demographics>
    </PatientRecord>
</MyDS>

Соответственно, здесь есть немного измененное преобразование, которое дает желаемый результат :

<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:x="cds_dt" xmlns:c="cds" exclude-result-prefixes="c x">
     <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="c:ContactPurpose/x:PurposeAsPlainText/text()">0</xsl:template>

     <xsl:template match="c:ContactPurpose/*"><xsl:apply-templates/></xsl:template>
</xsl:stylesheet>

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

<MyDS xmlns="cds" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <PatientRecord>
      <Demographics>
         <Contact>
            <ContactPurpose>0</ContactPurpose>
            <ContactPurpose>Call</ContactPurpose>
         </Contact>
      </Demographics>
   </PatientRecord>
</MyDS>
1 голос
/ 05 марта 2012
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cds="cds_dt" exclude-result-prefixes="cds">
<!-- identity transform - just copy things that don't have a better rule -->
<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
</xsl:template>

<!- a rule for what needs changing -->
<xsl:template match="ContactPurpose[cds:PurposeAsPlainText] ">
    <ContactPurpose>O</ContactPurpose>
</xsl:template>
</xsl:stylesheet>
...