0

同じ名前で異なる値のXMLノードをグループ化する方法を理解しようとしています。

私が使用しているWebサービスは、次のようなXmlElementを返します。

<Items>
    <Item>
        <Name name="Name">Item 1</Name>
        <Description name="Description">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit.
        </Description>
        <AssociatedItems name="Associated Items">Item 2</AssociatedItems>
        <AssociatedItems name="Associated Items">Item 3</AssociatedItems>
        <AssociatedItems name="Associated Items">Item 4</AssociatedItems>
        <AssociatedItems name="Associated Items">Item 5</AssociatedItems>
    </Item>
</Items>

各ノードをHTMLタグに変換しています

protected void lnkItem_Click(object sender, EventArgs e)
{
    LinkButton link = (LinkButton)sender;
    GridViewRow row = (GridViewRow)link.Parent.Parent;

    string id = gv.DataKeys[row.RowIndex]["id"].ToString();

    PublicApiAsmxServiceSoapClient service = new PublicApiAsmxServiceSoapClient("PublicApiAsmxServiceSoap", WEB_SERVICE_URL);
    XmlElement xml = service.ItemGetAsXml(id);
    XElement nodes = XElement.Parse(xml.InnerXml);

    foreach (var node in nodes.Elements())
    {
        InsertHTML(node);
    }
}

private void InsertHTML(XElement node)
{
    if (node.Value == string.Empty)
        return;

    pnl.ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("<h3>{0}</h3>", node.Attribute("name").Value)));
    pnl.ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("<p>{0}</p>", node.Value)));
}

今の私のコードでは、HTML出力は次のようになります。

<h3>Name</h3>
<p>Item 1</p>
<h3>Description</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<h3>Associated Items</h3>
<p>Item 2</p>
<h3>Associated Items</h3>
<p>Item 3</p>
<h3>Associated Items</h3>
<p>Item 4</p>
<h3>Associated Items</h3>
<p>Item 5</p>

順序付けされていないリストと同じノードをグループ化する方法はありますか?このようなもの、おそらく:

<h3>Name</h3>
<p>Item 1</p>
<h3>Description</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<h3>Associated Items</h3>
<ul>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
</ul>

ありがとうございました!(よろしくお願いします。)

PS繰り返す子ノードはAssociatedTermsのみに限定されません。同じ名前の子ノードが繰り返される可能性があります。

4

3 に答える 3

1

生成されるものは重複の数に依存するため、ジェネレータを使用してグループ化に基づいて要素を生成するのが最も簡単です。

私が理解しているように、あなたは要素名とname属性の値でグループ化しています。次にh3、グループに複数の要素があるかどうかに応じて、後続の要素を生成します。 p単一の要素があるul場合、または複数の要素がある場合。

IEnumerable<XElement> GroupedElements(XElement root)
{
    var groupedItems =
        from element in root.Elements()
        group element
        by new
        {
            Element = element.Name,
            Name = (string)element.Attribute("name"),
        };
    foreach (var g in groupedItems)
    {
        yield return new XElement("h3", g.Key.Name);
        var isMultiple = g.Skip(1).Any();
        if (isMultiple)
            yield return new XElement("ul",
                from item in g
                select new XElement("li", item.Value.Trim())
            );
        else
            yield return new XElement("p", g.Single().Value.Trim());
    }
}
var xmlStr = @"<Items>
    <Item>
        <Name name=""Name"">Item 1</Name>
        <Description name=""Description"">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit.
        </Description>
        <AssociatedItems name=""Associated Items"">Item 2</AssociatedItems>
        <AssociatedItems name=""Associated Items"">Item 3</AssociatedItems>
        <AssociatedItems name=""Associated Items"">Item 4</AssociatedItems>
        <AssociatedItems name=""Associated Items"">Item 5</AssociatedItems>
    </Item>
</Items>";
var doc = XDocument.Parse(xmlStr);
var transformed = new XElement("div", 
    from item in doc.XPathSelectElements("/Items/Item")
    select GroupedElements(item)
);

次のようになります。

<div>
  <h3>Name</h3>
  <p>Item 1</p>
  <h3>Description</h3>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
  <h3>Associated Items</h3>
  <ul>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
  </ul>
</div>
于 2012-07-26T05:36:34.767 に答える
0

それが最善の解決策かどうかはわかりませんが、このようなことを試すことができます

       List<string> items = new List<string>();
          XmlReader rdr = XmlReader.Create(new System.IO.StringReader(xml));
          while (rdr.Read())
          {
            if (rdr.NodeType == XmlNodeType.Element)
            {
                InsertHTML(rdr.LocalName.ToString(), rdr.Value.ToString());
            }
          }
        private void InsertHTML(string name, string value)
        {
            if (value == string.Empty)
                return;
            if(name=="AssociatedItems")
             {

               items.add(value);
             }
             else
             {
            pnl.ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("<h3>{0}</h3>", name)));
            pnl.ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("<p>{0}</p>", value)));
             }
        }
           pnl.ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("<h3>{0}</h3>", "Associated Items")));
           pnl.ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("<ul>")));
        foreach(var item in items)
        {

          pnl.ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("<li>{0}</li>", item)));

        }
         pnl.ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("</ul>")));
于 2012-07-26T03:25:16.763 に答える
0

XSLTを使用したい場合は、次を使用できます。

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

  <xsl:key name="grouping" match="Item/*" use="@name"/>

  <xsl:template match="Item">
    <xsl:apply-templates
         select="*[generate-id(.)=generate-id(key('grouping', @name)[1])]"/>
  </xsl:template>

  <xsl:template match="Item/*">
    <h3><xsl:value-of select="@name"/></h3>
    <xsl:choose>
      <xsl:when test="count(key('grouping', @name))=1">
        <p><xsl:value-of select="normalize-space(.)"/></p>
      </xsl:when>
      <xsl:otherwise>
        <li>
          <xsl:for-each select="key('grouping', @name)">
            <ul><xsl:value-of select="normalize-space(.)"/></ul>
          </xsl:for-each>
        </li>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>
于 2012-07-26T07:42:50.167 に答える